[llvm] r206732 - Implement builtins for safe division: safe.sdiv.iN, safe.udiv.iN, safe.srem.iN,

Chandler Carruth chandlerc at google.com
Mon Apr 21 00:21:22 PDT 2014


Here is a GDB backtrace of the crasher for you:

Program received signal SIGSEGV, Segmentation fault.
llvm::Instruction::getParent (this=0x0) at
../include/llvm/IR/Instruction.h:54
54        inline       BasicBlock *getParent()       { return Parent; }
(gdb) bt
#0  llvm::Instruction::getParent (this=0x0) at
../include/llvm/IR/Instruction.h:54
#1  0x000000000100f5ca in (anonymous
namespace)::CodeGenPrepare::OptimizeCallInst (this=0x2809b20, CI=0x27f3418)
at ../lib/CodeGen/CodeGenPrepare.cpp:940
#2  0x000000000100ae14 in (anonymous
namespace)::CodeGenPrepare::OptimizeInst (this=0x2809b20, I=0x27f3418) at
../lib/CodeGen/CodeGenPrepare.cpp:3294
#3  0x000000000100a5d9 in (anonymous
namespace)::CodeGenPrepare::OptimizeBlock (this=0x2809b20, BB=...) at
../lib/CodeGen/CodeGenPrepare.cpp:3314
#4  0x00000000010095fd in (anonymous
namespace)::CodeGenPrepare::runOnFunction (this=0x2809b20, F=...) at
../lib/CodeGen/CodeGenPrepare.cpp:219
#5  0x00000000013f052b in llvm::FPPassManager::runOnFunction
(this=0x2801ef0, F=...) at ../lib/IR/LegacyPassManager.cpp:1540
#6  0x00000000013f0838 in llvm::FPPassManager::runOnModule (this=0x2801ef0,
M=...) at ../lib/IR/LegacyPassManager.cpp:1560
#7  0x00000000013f0efa in (anonymous namespace)::MPPassManager::runOnModule
(this=0x27eb860, M=...) at ../lib/IR/LegacyPassManager.cpp:1618
#8  0x00000000013f0aee in llvm::legacy::PassManagerImpl::run
(this=0x27eb570, M=...) at ../lib/IR/LegacyPassManager.cpp:1725
#9  0x00000000013f13a1 in llvm::legacy::PassManager::run
(this=0x7fffffffdfc0, M=...) at ../lib/IR/LegacyPassManager.cpp:1760
#10 0x000000000069a4bf in compileModule (argv=0x7fffffffe418, Context=...)
at ../tools/llc/llc.cpp:355
#11 0x0000000000699632 in main (argc=5, argv=0x7fffffffe418) at
../tools/llc/llc.cpp:201



On Mon, Apr 21, 2014 at 12:13 AM, Chandler Carruth <chandlerc at google.com>wrote:

> This has broken roughly all of the build bots:
> http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-debian-fast/builds/14859
>
> I'm going to revert as they've been broken for an hour now.
>
>
> On Sun, Apr 20, 2014 at 10:33 PM, Michael Zolotukhin <
> mzolotukhin at apple.com> wrote:
>
>> Author: mzolotukhin
>> Date: Mon Apr 21 00:33:09 2014
>> New Revision: 206732
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=206732&view=rev
>> Log:
>> Implement builtins for safe division: safe.sdiv.iN, safe.udiv.iN,
>> safe.srem.iN,
>> safe.urem.iN (iN = i8, i16, i32, or i64).
>>
>>
>> Added:
>>     llvm/trunk/test/CodeGen/ARM64/SafeDivRemIntrinsics-Opts.ll
>>     llvm/trunk/test/CodeGen/ARM64/SafeDivRemIntrinsics.ll
>>     llvm/trunk/test/CodeGen/X86/SafeDivRemIntrinsics-Opts.ll
>>     llvm/trunk/test/CodeGen/X86/SafeDivRemIntrinsics.ll
>> Modified:
>>     llvm/trunk/include/llvm/IR/Intrinsics.td
>>     llvm/trunk/include/llvm/Target/TargetLowering.h
>>     llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
>>     llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp
>>     llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.cpp
>>
>> Modified: llvm/trunk/include/llvm/IR/Intrinsics.td
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Intrinsics.td?rev=206732&r1=206731&r2=206732&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/IR/Intrinsics.td (original)
>> +++ llvm/trunk/include/llvm/IR/Intrinsics.td Mon Apr 21 00:33:09 2014
>> @@ -444,6 +444,19 @@ def int_umul_with_overflow : Intrinsic<[
>>                                         [LLVMMatchType<0>,
>> LLVMMatchType<0>],
>>                                         [IntrNoMem]>;
>>
>> +def int_safe_udiv : Intrinsic<[llvm_anyint_ty, llvm_i1_ty],
>> +                              [LLVMMatchType<0>, LLVMMatchType<0>],
>> +                              [IntrNoMem]>;
>> +def int_safe_urem : Intrinsic<[llvm_anyint_ty, llvm_i1_ty],
>> +                              [LLVMMatchType<0>, LLVMMatchType<0>],
>> +                              [IntrNoMem]>;
>> +def int_safe_sdiv : Intrinsic<[llvm_anyint_ty, llvm_i1_ty],
>> +                              [LLVMMatchType<0>, LLVMMatchType<0>],
>> +                              [IntrNoMem]>;
>> +def int_safe_srem : Intrinsic<[llvm_anyint_ty, llvm_i1_ty],
>> +                              [LLVMMatchType<0>, LLVMMatchType<0>],
>> +                              [IntrNoMem]>;
>> +
>>  //===------------------------- Memory Use Markers
>> -------------------------===//
>>  //
>>  def int_lifetime_start  : Intrinsic<[],
>>
>> Modified: llvm/trunk/include/llvm/Target/TargetLowering.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=206732&r1=206731&r2=206732&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Target/TargetLowering.h (original)
>> +++ llvm/trunk/include/llvm/Target/TargetLowering.h Mon Apr 21 00:33:09
>> 2014
>> @@ -218,6 +218,10 @@ public:
>>    /// Return true if pow2 div is cheaper than a chain of srl/add/sra.
>>    bool isPow2DivCheap() const { return Pow2DivIsCheap; }
>>
>> +  /// Return true if Div never traps, returns 0 when div by 0 and return
>> TMin,
>> +  /// when sdiv TMin by -1.
>> +  bool isDivWellDefined() const { return DivIsWellDefined; }
>> +
>>    /// Return true if Flow Control is an expensive operation that should
>> be
>>    /// avoided.
>>    bool isJumpExpensive() const { return JumpIsExpensive; }
>> @@ -1026,6 +1030,13 @@ protected:
>>    /// signed divide by power of two, and let the target handle it.
>>    void setPow2DivIsCheap(bool isCheap = true) { Pow2DivIsCheap =
>> isCheap; }
>>
>> +  /// Tells the code-generator that it is safe to execute
>> sdiv/udiv/srem/urem
>> +  /// even when RHS is 0. It is also safe to execute sdiv/srem when LHS
>> is
>> +  /// SignedMinValue and RHS is -1.
>> +  void setDivIsWellDefined (bool isWellDefined = true) {
>> +    DivIsWellDefined = isWellDefined;
>> +  }
>> +
>>    /// Add the specified register class as an available regclass for the
>>    /// specified value type. This indicates the selector can handle
>> values of
>>    /// that class natively.
>> @@ -1441,6 +1452,11 @@ private:
>>    /// signed divide by power of two, and let the target handle it.
>>    bool Pow2DivIsCheap;
>>
>> +  /// Tells the code-generator that it is safe to execute
>> sdiv/udiv/srem/urem
>> +  /// even when RHS is 0. It is also safe to execute sdiv/srem when LHS
>> is
>> +  /// SignedMinValue and RHS is -1.
>> +  bool DivIsWellDefined;
>> +
>>    /// Tells the code generator that it shouldn't generate extra flow
>> control
>>    /// instructions and should attempt to combine flow control
>> instructions via
>>    /// predication.
>>
>> Modified: llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp?rev=206732&r1=206731&r2=206732&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp Mon Apr 21 00:33:09 2014
>> @@ -688,6 +688,293 @@ bool CodeGenPrepare::OptimizeCallInst(Ca
>>      }
>>      return true;
>>    }
>> +  // Lower all uses of llvm.safe.[us]{div|rem}...
>> +  if (II &&
>> +      (II->getIntrinsicID() == Intrinsic::safe_sdiv ||
>> +       II->getIntrinsicID() == Intrinsic::safe_udiv ||
>> +       II->getIntrinsicID() == Intrinsic::safe_srem ||
>> +       II->getIntrinsicID() == Intrinsic::safe_urem)) {
>> +    // Given
>> +    //   result_struct = type {iN, i1}
>> +    //   %R = call result_struct llvm.safe.sdiv.iN(iN %x, iN %y)
>> +    // Expand it to actual IR, which produces result to the same
>> variable %R.
>> +    // First element of the result %R.1 is the result of division, second
>> +    // element shows whether the division was correct or not.
>> +    // If %y is 0, %R.1 is 0, %R.2 is 1.                            (1)
>> +    // If %x is minSignedValue and %y is -1, %R.1 is %x, %R.2 is 1. (2)
>> +    // In other cases %R.1 is (sdiv %x, %y), %R.2 is 0.             (3)
>> +    //
>> +    // Similar applies to srem, udiv, and urem builtins, except that in
>> unsigned
>> +    // variants we don't check condition (2).
>> +
>> +    bool IsSigned;
>> +    BinaryOperator::BinaryOps Op;
>> +    switch (II->getIntrinsicID()) {
>> +      case Intrinsic::safe_sdiv:
>> +        IsSigned = true;
>> +        Op = Instruction::SDiv;
>> +        break;
>> +      case Intrinsic::safe_udiv:
>> +        IsSigned = false;
>> +        Op = Instruction::UDiv;
>> +        break;
>> +      case Intrinsic::safe_srem:
>> +        IsSigned = true;
>> +        Op = Instruction::SRem;
>> +        break;
>> +      case Intrinsic::safe_urem:
>> +        IsSigned = false;
>> +        Op = Instruction::URem;
>> +        break;
>> +      default:
>> +        llvm_unreachable("Only Div/Rem intrinsics are handled here.");
>> +    }
>> +
>> +    Value *LHS = II->getOperand(0), *RHS = II->getOperand(1);
>> +    bool DivWellDefined = TLI && TLI->isDivWellDefined();
>> +
>> +    bool ResultNeeded[2] = {false, false};
>> +    SmallVector<User*, 1> ResultsUsers[2];
>> +    bool BadCase = false;
>> +    for (User *U: II->users()) {
>> +      ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(U);
>> +      if (!EVI || EVI->getNumIndices() > 1 || EVI->getIndices()[0] > 1) {
>> +        BadCase = true;
>> +        break;
>> +      }
>> +      ResultNeeded[EVI->getIndices()[0]] = true;
>> +      ResultsUsers[EVI->getIndices()[0]].push_back(U);
>> +    }
>> +    // Behave conservatively, if there is an unusual user of the results.
>> +    if (BadCase)
>> +      ResultNeeded[0] = ResultNeeded[1] = true;
>> +
>> +    // Early exit if non of the results is ever used.
>> +    if (!ResultNeeded[0] && !ResultNeeded[1]) {
>> +      II->eraseFromParent();
>> +      return true;
>> +    }
>> +
>> +    // Early exit if the second result (flag) isn't used and target
>> +    // div-instruction computes exactly what we want to get as the first
>> result
>> +    // and never traps.
>> +    if (ResultNeeded[0] && !ResultNeeded[1] && DivWellDefined) {
>> +      BinaryOperator *Div = BinaryOperator::Create(Op, LHS, RHS);
>> +      Div->insertAfter(II);
>> +      for (User *U: ResultsUsers[0]) {
>> +        Instruction *UserInst = dyn_cast<Instruction>(U);
>> +        assert(UserInst && "Unexpected null-instruction");
>> +        UserInst->replaceAllUsesWith(Div);
>> +        UserInst->eraseFromParent();
>> +      }
>> +      II->eraseFromParent();
>> +      CurInstIterator = Div;
>> +      ModifiedDT = true;
>> +      return true;
>> +    }
>> +
>> +    // Check if the flag is used to jump out to a 'trap' block
>> +    // If it's the case, we want to use this block directly when we
>> create
>> +    // branches after comparing with 0 and comparing with -1 (signed
>> case).
>> +    // We can do it only iff we can track all the uses of the flag, i.e.
>> the
>> +    // only users are EXTRACTVALUE-insns, and their users are conditional
>> +    // branches, targeting the same 'trap' basic block.
>> +    BasicBlock *TrapBB = nullptr;
>> +    bool DoRelinkTrap = true;
>> +    for (User *FlagU: ResultsUsers[1]) {
>> +      for (User *U: FlagU->users()) {
>> +        BranchInst *TrapBranch = dyn_cast<BranchInst>(U);
>> +        // If the user isn't a branch-insn, or it jumps to another BB,
>> don't
>> +        // try to use TrapBB in the lowering.
>> +        if (!TrapBranch || (TrapBB && TrapBB !=
>> TrapBranch->getSuccessor(0))) {
>> +          DoRelinkTrap = false;
>> +          break;
>> +        }
>> +        TrapBB = TrapBranch->getSuccessor(0);
>> +      }
>> +    }
>> +    if (!TrapBB)
>> +      DoRelinkTrap = false;
>> +    // We want to reuse TrapBB if possible, because in that case we can
>> avoid
>> +    // creating new basic blocks and thus overcomplicating the IR.
>> However, if
>> +    // DIV instruction isn't well defined, we still need those blocks to
>> model
>> +    // well-defined behaviour. Thus, we can't reuse TrapBB in this case.
>> +    if (!DivWellDefined)
>> +      DoRelinkTrap = false;
>> +
>> +    Value *MinusOne = Constant::getAllOnesValue(LHS->getType());
>> +    Value *Zero = Constant::getNullValue(LHS->getType());
>> +
>> +    // Split the original BB and create other basic blocks that will be
>> used
>> +    // for checks.
>> +    BasicBlock *StartBB = II->getParent();
>> +    BasicBlock::iterator SplitPt = ++(BasicBlock::iterator(II));
>> +    BasicBlock *NextBB = StartBB->splitBasicBlock(SplitPt, "div.end");
>> +
>> +    BasicBlock *DivByZeroBB;
>> +    if (!DoRelinkTrap) {
>> +      DivByZeroBB = BasicBlock::Create(II->getContext(), "div.divz",
>> +                                       NextBB->getParent(), NextBB);
>> +      BranchInst::Create(NextBB, DivByZeroBB);
>> +    }
>> +    BasicBlock *DivBB = BasicBlock::Create(II->getContext(), "div.div",
>> +                                           NextBB->getParent(), NextBB);
>> +    BranchInst::Create(NextBB, DivBB);
>> +
>> +    // For signed variants, check the condition (2):
>> +    // LHS == SignedMinValue, RHS == -1.
>> +    Value *CmpMinusOne;
>> +    Value *CmpMinValue;
>> +    BasicBlock *ChkDivMinBB;
>> +    BasicBlock *DivMinBB;
>> +    Value *MinValue;
>> +    if (IsSigned) {
>> +      APInt SignedMinValue =
>> +
>>  APInt::getSignedMinValue(LHS->getType()->getPrimitiveSizeInBits());
>> +      MinValue = Constant::getIntegerValue(LHS->getType(),
>> SignedMinValue);
>> +      ChkDivMinBB = BasicBlock::Create(II->getContext(), "div.chkdivmin",
>> +                                       NextBB->getParent(), NextBB);
>> +      BranchInst::Create(NextBB, ChkDivMinBB);
>> +      if (!DoRelinkTrap) {
>> +        DivMinBB = BasicBlock::Create(II->getContext(), "div.divmin",
>> +                                      NextBB->getParent(), NextBB);
>> +        BranchInst::Create(NextBB, DivMinBB);
>> +      }
>> +      CmpMinusOne = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ,
>> +                                    RHS, MinusOne, "cmp.rhs.minus.one",
>> +                                    ChkDivMinBB->getTerminator());
>> +      CmpMinValue = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ,
>> +                                    LHS, MinValue, "cmp.lhs.signed.min",
>> +                                    ChkDivMinBB->getTerminator());
>> +      BinaryOperator *CmpSignedOvf =
>> BinaryOperator::Create(Instruction::And,
>> +                                                            CmpMinusOne,
>> +                                                            CmpMinValue);
>> +      // Here we're interested in the case when both %x is TMin and %y
>> is -1.
>> +      // In this case the result will overflow.
>> +      // If that's not the case, we can perform usual division. These
>> blocks
>> +      // will be inserted after DivByZero, so the division will be safe.
>> +      CmpSignedOvf->insertBefore(ChkDivMinBB->getTerminator());
>> +      BranchInst::Create(DoRelinkTrap ? TrapBB : DivMinBB, DivBB,
>> CmpSignedOvf,
>> +                         ChkDivMinBB->getTerminator());
>> +      ChkDivMinBB->getTerminator()->eraseFromParent();
>> +    }
>> +
>> +    // Check the condition (1):
>> +    // RHS == 0.
>> +    Value *CmpDivZero = CmpInst::Create(Instruction::ICmp,
>> CmpInst::ICMP_EQ,
>> +                                        RHS, Zero, "cmp.rhs.zero",
>> +                                        StartBB->getTerminator());
>> +
>> +    // If RHS != 0, we want to check condition (2) in signed case, or
>> proceed
>> +    // to usual division in unsigned case.
>> +    BranchInst::Create(DoRelinkTrap ? TrapBB : DivByZeroBB,
>> +                       IsSigned ? ChkDivMinBB : DivBB, CmpDivZero,
>> +                       StartBB->getTerminator());
>> +    StartBB->getTerminator()->eraseFromParent();
>> +
>> +    // At the moment we have all the control flow created. We just need
>> to
>> +    // insert DIV and PHI (if needed) to get the result value.
>> +    Instruction *DivRes, *FlagRes;
>> +    Instruction *InsPoint = nullptr;
>> +    if (ResultNeeded[0]) {
>> +      BinaryOperator *Div = BinaryOperator::Create(Op, LHS, RHS);
>> +      if (DivWellDefined) {
>> +        // The result value is the result of DIV operation placed right
>> at the
>> +        // original place of the intrinsic.
>> +        Div->insertAfter(II);
>> +        DivRes = Div;
>> +      } else {
>> +        // The result is a PHI-node.
>> +        Div->insertBefore(DivBB->getTerminator());
>> +        PHINode *DivResPN =
>> +          PHINode::Create(LHS->getType(), IsSigned ? 3 : 2,
>> "div.res.phi",
>> +                          NextBB->begin());
>> +        DivResPN->addIncoming(Div, DivBB);
>> +        DivResPN->addIncoming(Zero, DivByZeroBB);
>> +        if (IsSigned)
>> +          DivResPN->addIncoming(MinValue, DivMinBB);
>> +        DivRes = DivResPN;
>> +        InsPoint = DivResPN;
>> +      }
>> +    }
>> +
>> +    // Prepare a value for the second result (flag) if it is needed.
>> +    if (ResultNeeded[1] && !DoRelinkTrap) {
>> +      Type *FlagTy = II->getType()->getStructElementType(1);
>> +      PHINode *FlagResPN =
>> +        PHINode::Create(FlagTy, IsSigned ? 3 : 2, "div.flag.phi",
>> +                        NextBB->begin());
>> +      FlagResPN->addIncoming(Constant::getNullValue(FlagTy), DivBB);
>> +      FlagResPN->addIncoming(Constant::getAllOnesValue(FlagTy),
>> DivByZeroBB);
>> +      if (IsSigned)
>> +        FlagResPN->addIncoming(Constant::getAllOnesValue(FlagTy),
>> DivMinBB);
>> +      FlagRes = FlagResPN;
>> +      if (!InsPoint)
>> +        InsPoint = FlagRes;
>> +    }
>> +
>> +    // If possible, propagate the results to the user. Otherwise, create
>> alloca,
>> +    // and create a struct with the results on stack.
>> +    if (!BadCase) {
>> +      if (ResultNeeded[0]) {
>> +        for (User *U: ResultsUsers[0]) {
>> +          Instruction *UserInst = dyn_cast<Instruction>(U);
>> +          assert(UserInst && "Unexpected null-instruction");
>> +          UserInst->replaceAllUsesWith(DivRes);
>> +          UserInst->eraseFromParent();
>> +        }
>> +      }
>> +      if (ResultNeeded[1]) {
>> +        for (User *FlagU: ResultsUsers[1]) {
>> +          Instruction *FlagUInst = dyn_cast<Instruction>(FlagU);
>> +          if (DoRelinkTrap) {
>> +            // Replace
>> +            //   %flag = extractvalue %intrinsic.res, 1
>> +            //   br i1 %flag, label %trap.bb, label %other.bb
>> +            // With
>> +            //   br label %other.bb
>> +            // We've already created checks that are pointing to %
>> trap.bb, there
>> +            // is no need to have the same checks here.
>> +            for (User *U: FlagUInst->users()) {
>> +              BranchInst *TrapBranch = dyn_cast<BranchInst>(U);
>> +              BasicBlock *CurBB = TrapBranch->getParent();
>> +              BasicBlock *SuccessorBB = TrapBranch->getSuccessor(1);
>> +              CurBB->getTerminator()->eraseFromParent();
>> +              BranchInst::Create(SuccessorBB, CurBB);
>> +            }
>> +          } else {
>> +            FlagUInst->replaceAllUsesWith(FlagRes);
>> +          }
>> +          dyn_cast<Instruction>(FlagUInst)->eraseFromParent();
>> +        }
>> +      }
>> +    } else {
>> +      // Create alloca, store our new values to it, and then load the
>> final
>> +      // result from it.
>> +      Constant *Idx0 =
>> ConstantInt::get(Type::getInt32Ty(II->getContext()), 0);
>> +      Constant *Idx1 =
>> ConstantInt::get(Type::getInt32Ty(II->getContext()), 1);
>> +      Value *Idxs_DivRes[2] = {Idx0, Idx0};
>> +      Value *Idxs_FlagRes[2] = {Idx0, Idx1};
>> +      Value *NewRes = new llvm::AllocaInst(II->getType(), 0,
>> "div.res.ptr", II);
>> +      Instruction *ResDivAddr = GetElementPtrInst::Create(NewRes,
>> Idxs_DivRes);
>> +      Instruction *ResFlagAddr =
>> +        GetElementPtrInst::Create(NewRes, Idxs_FlagRes);
>> +      ResDivAddr->insertAfter(InsPoint);
>> +      ResFlagAddr->insertAfter(ResDivAddr);
>> +      StoreInst *StoreResDiv = new StoreInst(DivRes, ResDivAddr);
>> +      StoreInst *StoreResFlag = new StoreInst(FlagRes, ResFlagAddr);
>> +      StoreResDiv->insertAfter(ResFlagAddr);
>> +      StoreResFlag->insertAfter(StoreResDiv);
>> +      LoadInst *LoadRes = new LoadInst(NewRes, "div.res");
>> +      LoadRes->insertAfter(StoreResFlag);
>> +      II->replaceAllUsesWith(LoadRes);
>> +    }
>> +
>> +    II->eraseFromParent();
>> +    CurInstIterator = StartBB->end();
>> +    ModifiedDT = true;
>> +    return true;
>> +  }
>>
>>    if (II && TLI) {
>>      SmallVector<Value*, 2> PtrOps;
>>
>> Modified: llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp?rev=206732&r1=206731&r2=206732&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp Mon Apr 21 00:33:09 2014
>> @@ -682,6 +682,7 @@ TargetLoweringBase::TargetLoweringBase(c
>>    HasMultipleConditionRegisters = false;
>>    IntDivIsCheap = false;
>>    Pow2DivIsCheap = false;
>> +  DivIsWellDefined = false;
>>    JumpIsExpensive = false;
>>    PredictableSelectIsExpensive = false;
>>    MaskAndBranchFoldingIsLegal = false;
>>
>> Modified: llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.cpp?rev=206732&r1=206731&r2=206732&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.cpp (original)
>> +++ llvm/trunk/lib/Target/ARM64/ARM64ISelLowering.cpp Mon Apr 21 00:33:09
>> 2014
>> @@ -435,6 +435,8 @@ ARM64TargetLowering::ARM64TargetLowering
>>
>>    setMinFunctionAlignment(2);
>>
>> +  setDivIsWellDefined(true);
>> +
>>    RequireStrictAlign = StrictAlign;
>>  }
>>
>>
>> Added: llvm/trunk/test/CodeGen/ARM64/SafeDivRemIntrinsics-Opts.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM64/SafeDivRemIntrinsics-Opts.ll?rev=206732&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/ARM64/SafeDivRemIntrinsics-Opts.ll (added)
>> +++ llvm/trunk/test/CodeGen/ARM64/SafeDivRemIntrinsics-Opts.ll Mon Apr 21
>> 00:33:09 2014
>> @@ -0,0 +1,112 @@
>> +; RUN: llc < %s -march=arm64 | FileCheck %s
>> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>> +
>> +%divovf32 = type { i32, i1 }
>> +
>> +declare %divovf32 @llvm.safe.sdiv.i32(i32, i32) nounwind readnone
>> +declare %divovf32 @llvm.safe.udiv.i32(i32, i32) nounwind readnone
>> +
>> +; CHECK-LABEL: sdiv32_results_unused
>> +; CHECK: entry
>> +; CHECK-NEXT: ret
>> +define void @sdiv32_results_unused(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
>> +  ret void
>> +}
>> +
>> +; CHECK-LABEL: sdiv32_div_result_unused
>> +; CHECK-NOT: sdiv{{[    ]}}
>> +define i1 @sdiv32_div_result_unused(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
>> +  %bit = extractvalue %divovf32 %divr, 1
>> +  ret i1 %bit
>> +}
>> +
>> +; CHECK-LABEL: sdiv32_flag_result_unused
>> +; CHECK-NOT: cb
>> +; CHECK: sdiv{{[        ]}}
>> +define i32 @sdiv32_flag_result_unused(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
>> +  %div = extractvalue %divovf32 %divr, 0
>> +  ret i32 %div
>> +}
>> +
>> +; CHECK-LABEL: sdiv32_result_returned
>> +; CHECK: sdiv{{[        ]}}
>> +define %divovf32 @sdiv32_result_returned(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
>> +  ret %divovf32 %divr
>> +}
>> +
>> +; CHECK-LABEL: sdiv32_trap_relinked
>> +; CHECK-NOT: %div.divmin
>> +; CHECK-NOT: %div.divz
>> +define i32 @sdiv32_trap_relinked(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
>> +  %div = extractvalue %divovf32 %divr, 0
>> +  %bit = extractvalue %divovf32 %divr, 1
>> +  br i1 %bit, label %trap.bb, label %ok.bb
>> +trap.bb:
>> +  ret i32 7
>> +ok.bb:
>> +  ret i32 %div
>> +}
>> +
>> +; CHECK-LABEL: udiv32_results_unused
>> +; CHECK: entry
>> +; CHECK-NEXT: ret
>> +define void @udiv32_results_unused(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
>> +  ret void
>> +}
>> +
>> +; CHECK-LABEL: udiv32_div_result_unused
>> +; CHECK-NOT: udiv{{[    ]}}
>> +define i1 @udiv32_div_result_unused(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
>> +  %bit = extractvalue %divovf32 %divr, 1
>> +  ret i1 %bit
>> +}
>> +
>> +; CHECK-LABEL: udiv32_flag_result_unused
>> +; CHECK-NOT: cb
>> +; CHECK: udiv{{[        ]}}
>> +define i32 @udiv32_flag_result_unused(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
>> +  %div = extractvalue %divovf32 %divr, 0
>> +  ret i32 %div
>> +}
>> +
>> +; CHECK-LABEL: udiv32_result_returned
>> +; CHECK: udiv{{[        ]}}
>> +define %divovf32 @udiv32_result_returned(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
>> +  ret %divovf32 %divr
>> +}
>> +
>> +; CHECK-LABEL: udiv32_trap_relinked
>> +; CHECK-NOT: %div.divz
>> +define i32 @udiv32_trap_relinked(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
>> +  %div = extractvalue %divovf32 %divr, 0
>> +  %bit = extractvalue %divovf32 %divr, 1
>> +  br i1 %bit, label %trap.bb, label %ok.bb
>> +trap.bb:
>> +  ret i32 7
>> +ok.bb:
>> +  ret i32 %div
>> +}
>> +
>> +!llvm.ident = !{!0}
>> +
>> +!0 = metadata !{metadata !"clang version 3.5.0 "}
>>
>> Added: llvm/trunk/test/CodeGen/ARM64/SafeDivRemIntrinsics.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM64/SafeDivRemIntrinsics.ll?rev=206732&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/ARM64/SafeDivRemIntrinsics.ll (added)
>> +++ llvm/trunk/test/CodeGen/ARM64/SafeDivRemIntrinsics.ll Mon Apr 21
>> 00:33:09 2014
>> @@ -0,0 +1,152 @@
>> +; RUN: llc < %s -march=arm64 | FileCheck %s
>> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>> +
>> +%divovf8  = type { i8, i1 }
>> +%divovf16 = type { i16, i1 }
>> +%divovf32 = type { i32, i1 }
>> +%divovf64 = type { i64, i1 }
>> +
>> +declare %divovf8  @llvm.safe.sdiv.i8(i8, i8) nounwind readnone
>> +declare %divovf16 @llvm.safe.sdiv.i16(i16, i16) nounwind readnone
>> +declare %divovf32 @llvm.safe.sdiv.i32(i32, i32) nounwind readnone
>> +declare %divovf64 @llvm.safe.sdiv.i64(i64, i64) nounwind readnone
>> +
>> +declare %divovf8  @llvm.safe.srem.i8(i8, i8) nounwind readnone
>> +declare %divovf16 @llvm.safe.srem.i16(i16, i16) nounwind readnone
>> +declare %divovf32 @llvm.safe.srem.i32(i32, i32) nounwind readnone
>> +declare %divovf64 @llvm.safe.srem.i64(i64, i64) nounwind readnone
>> +
>> +declare %divovf8  @llvm.safe.udiv.i8(i8, i8) nounwind readnone
>> +declare %divovf16 @llvm.safe.udiv.i16(i16, i16) nounwind readnone
>> +declare %divovf32 @llvm.safe.udiv.i32(i32, i32) nounwind readnone
>> +declare %divovf64 @llvm.safe.udiv.i64(i64, i64) nounwind readnone
>> +
>> +declare %divovf8  @llvm.safe.urem.i8(i8, i8) nounwind readnone
>> +declare %divovf16 @llvm.safe.urem.i16(i16, i16) nounwind readnone
>> +declare %divovf32 @llvm.safe.urem.i32(i32, i32) nounwind readnone
>> +declare %divovf64 @llvm.safe.urem.i64(i64, i64) nounwind readnone
>> +
>> +; CHECK-LABEL: sdiv8
>> +; CHECK: sdiv{{[       ]}}
>> +define %divovf8 @sdiv8(i8 %x, i8 %y) {
>> +entry:
>> +  %divr = call %divovf8 @llvm.safe.sdiv.i8(i8 %x, i8 %y)
>> +  ret %divovf8 %divr
>> +}
>> +; CHECK-LABEL: sdiv16
>> +; CHECK: sdiv{{[       ]}}
>> +define %divovf16 @sdiv16(i16 %x, i16 %y) {
>> +entry:
>> +  %divr = call %divovf16 @llvm.safe.sdiv.i16(i16 %x, i16 %y)
>> +  ret %divovf16 %divr
>> +}
>> +; CHECK-LABEL: sdiv32
>> +; CHECK: sdiv{{[       ]}}
>> +define %divovf32 @sdiv32(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
>> +  ret %divovf32 %divr
>> +}
>> +; CHECK-LABEL: sdiv64
>> +; CHECK: sdiv{{[       ]}}
>> +define %divovf64 @sdiv64(i64 %x, i64 %y) {
>> +entry:
>> +  %divr = call %divovf64 @llvm.safe.sdiv.i64(i64 %x, i64 %y)
>> +  ret %divovf64 %divr
>> +}
>> +; CHECK-LABEL: udiv8
>> +; CHECK: udiv{{[       ]}}
>> +define %divovf8 @udiv8(i8 %x, i8 %y) {
>> +entry:
>> +  %divr = call %divovf8 @llvm.safe.udiv.i8(i8 %x, i8 %y)
>> +  ret %divovf8 %divr
>> +}
>> +; CHECK-LABEL: udiv16
>> +; CHECK: udiv{{[       ]}}
>> +define %divovf16 @udiv16(i16 %x, i16 %y) {
>> +entry:
>> +  %divr = call %divovf16 @llvm.safe.udiv.i16(i16 %x, i16 %y)
>> +  ret %divovf16 %divr
>> +}
>> +; CHECK-LABEL: udiv32
>> +; CHECK: udiv{{[       ]}}
>> +define %divovf32 @udiv32(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
>> +  ret %divovf32 %divr
>> +}
>> +; CHECK-LABEL: udiv64
>> +; CHECK: udiv{{[       ]}}
>> +define %divovf64 @udiv64(i64 %x, i64 %y) {
>> +entry:
>> +  %divr = call %divovf64 @llvm.safe.udiv.i64(i64 %x, i64 %y)
>> +  ret %divovf64 %divr
>> +}
>> +; CHECK-LABEL: srem8
>> +; CHECK: sdiv{{[       ]}}
>> +; CHECK: msub{{[       ]}}
>> +define %divovf8 @srem8(i8 %x, i8 %y) {
>> +entry:
>> +  %remr = call %divovf8 @llvm.safe.srem.i8(i8 %x, i8 %y)
>> +  ret %divovf8 %remr
>> +}
>> +; CHECK-LABEL: srem16
>> +; CHECK: sdiv{{[       ]}}
>> +; CHECK: msub{{[       ]}}
>> +define %divovf16 @srem16(i16 %x, i16 %y) {
>> +entry:
>> +  %remr = call %divovf16 @llvm.safe.srem.i16(i16 %x, i16 %y)
>> +  ret %divovf16 %remr
>> +}
>> +; CHECK-LABEL: srem32
>> +; CHECK: sdiv{{[       ]}}
>> +; CHECK: msub{{[       ]}}
>> +define %divovf32 @srem32(i32 %x, i32 %y) {
>> +entry:
>> +  %remr = call %divovf32 @llvm.safe.srem.i32(i32 %x, i32 %y)
>> +  ret %divovf32 %remr
>> +}
>> +; CHECK-LABEL: srem64
>> +; CHECK: sdiv{{[       ]}}
>> +; CHECK: msub{{[       ]}}
>> +define %divovf64 @srem64(i64 %x, i64 %y) {
>> +entry:
>> +  %remr = call %divovf64 @llvm.safe.srem.i64(i64 %x, i64 %y)
>> +  ret %divovf64 %remr
>> +}
>> +; CHECK-LABEL: urem8
>> +; CHECK: udiv{{[       ]}}
>> +; CHECK: msub{{[       ]}}
>> +define %divovf8 @urem8(i8 %x, i8 %y) {
>> +entry:
>> +  %remr = call %divovf8 @llvm.safe.urem.i8(i8 %x, i8 %y)
>> +  ret %divovf8 %remr
>> +}
>> +; CHECK-LABEL: urem16
>> +; CHECK: udiv{{[       ]}}
>> +; CHECK: msub{{[       ]}}
>> +define %divovf16 @urem16(i16 %x, i16 %y) {
>> +entry:
>> +  %remr = call %divovf16 @llvm.safe.urem.i16(i16 %x, i16 %y)
>> +  ret %divovf16 %remr
>> +}
>> +; CHECK-LABEL: urem32
>> +; CHECK: udiv{{[       ]}}
>> +; CHECK: msub{{[       ]}}
>> +define %divovf32 @urem32(i32 %x, i32 %y) {
>> +entry:
>> +  %remr = call %divovf32 @llvm.safe.urem.i32(i32 %x, i32 %y)
>> +  ret %divovf32 %remr
>> +}
>> +; CHECK-LABEL: urem64
>> +; CHECK: udiv{{[       ]}}
>> +; CHECK: msub{{[       ]}}
>> +define %divovf64 @urem64(i64 %x, i64 %y) {
>> +entry:
>> +  %remr = call %divovf64 @llvm.safe.urem.i64(i64 %x, i64 %y)
>> +  ret %divovf64 %remr
>> +}
>> +
>> +!llvm.ident = !{!0}
>> +
>> +!0 = metadata !{metadata !"clang version 3.5.0 "}
>>
>> Added: llvm/trunk/test/CodeGen/X86/SafeDivRemIntrinsics-Opts.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/SafeDivRemIntrinsics-Opts.ll?rev=206732&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/X86/SafeDivRemIntrinsics-Opts.ll (added)
>> +++ llvm/trunk/test/CodeGen/X86/SafeDivRemIntrinsics-Opts.ll Mon Apr 21
>> 00:33:09 2014
>> @@ -0,0 +1,110 @@
>> +; RUN: llc < %s | FileCheck %s
>> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>> +
>> +%divovf32 = type { i32, i1 }
>> +
>> +declare %divovf32 @llvm.safe.sdiv.i32(i32, i32) nounwind readnone
>> +declare %divovf32 @llvm.safe.udiv.i32(i32, i32) nounwind readnone
>> +
>> +; CHECK-LABEL: sdiv32_results_unused
>> +; CHECK: entry
>> +; CHECK-NEXT: ret
>> +define void @sdiv32_results_unused(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
>> +  ret void
>> +}
>> +
>> +; CHECK-LABEL: sdiv32_div_result_unused
>> +; CHECK-NOT: idiv
>> +define i1 @sdiv32_div_result_unused(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
>> +  %bit = extractvalue %divovf32 %divr, 1
>> +  ret i1 %bit
>> +}
>> +
>> +; CHECK-LABEL: sdiv32_flag_result_unused
>> +; CHECK: idiv
>> +define i32 @sdiv32_flag_result_unused(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
>> +  %div = extractvalue %divovf32 %divr, 0
>> +  ret i32 %div
>> +}
>> +
>> +; CHECK-LABEL: sdiv32_result_returned
>> +; CHECK: idiv
>> +define %divovf32 @sdiv32_result_returned(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
>> +  ret %divovf32 %divr
>> +}
>> +
>> +; CHECK-LABEL: sdiv32_trap_relinked
>> +; CHECK: %div.div{{min|z}}
>> +define i32 @sdiv32_trap_relinked(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
>> +  %div = extractvalue %divovf32 %divr, 0
>> +  %bit = extractvalue %divovf32 %divr, 1
>> +  br i1 %bit, label %trap.bb, label %ok.bb
>> +trap.bb:
>> +  ret i32 7
>> +ok.bb:
>> +  ret i32 %div
>> +}
>> +
>> +; CHECK-LABEL: udiv32_results_unused
>> +; CHECK: entry
>> +; CHECK-NEXT: ret
>> +define void @udiv32_results_unused(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
>> +  ret void
>> +}
>> +
>> +; CHECK-LABEL: udiv32_div_result_unused
>> +; CHECK-NOT: udiv{{[    ]}}
>> +define i1 @udiv32_div_result_unused(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
>> +  %bit = extractvalue %divovf32 %divr, 1
>> +  ret i1 %bit
>> +}
>> +
>> +; CHECK-LABEL: udiv32_flag_result_unused
>> +; CHECK-NOT: cb
>> +; CHECK: {{[   ]}}div
>> +define i32 @udiv32_flag_result_unused(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
>> +  %div = extractvalue %divovf32 %divr, 0
>> +  ret i32 %div
>> +}
>> +
>> +; CHECK-LABEL: udiv32_result_returned
>> +; CHECK: {{[   ]}}div
>> +define %divovf32 @udiv32_result_returned(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
>> +  ret %divovf32 %divr
>> +}
>> +
>> +; CHECK-LABEL: udiv32_trap_relinked
>> +; CHECK: %div.divz
>> +define i32 @udiv32_trap_relinked(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
>> +  %div = extractvalue %divovf32 %divr, 0
>> +  %bit = extractvalue %divovf32 %divr, 1
>> +  br i1 %bit, label %trap.bb, label %ok.bb
>> +trap.bb:
>> +  ret i32 7
>> +ok.bb:
>> +  ret i32 %div
>> +}
>> +
>> +!llvm.ident = !{!0}
>> +
>> +!0 = metadata !{metadata !"clang version 3.5.0 "}
>>
>> Added: llvm/trunk/test/CodeGen/X86/SafeDivRemIntrinsics.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/SafeDivRemIntrinsics.ll?rev=206732&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/X86/SafeDivRemIntrinsics.ll (added)
>> +++ llvm/trunk/test/CodeGen/X86/SafeDivRemIntrinsics.ll Mon Apr 21
>> 00:33:09 2014
>> @@ -0,0 +1,144 @@
>> +; RUN: llc < %s | FileCheck %s
>> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>> +
>> +%divovf8  = type { i8, i1 }
>> +%divovf16 = type { i16, i1 }
>> +%divovf32 = type { i32, i1 }
>> +%divovf64 = type { i64, i1 }
>> +
>> +declare %divovf8  @llvm.safe.sdiv.i8(i8, i8) nounwind readnone
>> +declare %divovf16 @llvm.safe.sdiv.i16(i16, i16) nounwind readnone
>> +declare %divovf32 @llvm.safe.sdiv.i32(i32, i32) nounwind readnone
>> +declare %divovf64 @llvm.safe.sdiv.i64(i64, i64) nounwind readnone
>> +
>> +declare %divovf8  @llvm.safe.srem.i8(i8, i8) nounwind readnone
>> +declare %divovf16 @llvm.safe.srem.i16(i16, i16) nounwind readnone
>> +declare %divovf32 @llvm.safe.srem.i32(i32, i32) nounwind readnone
>> +declare %divovf64 @llvm.safe.srem.i64(i64, i64) nounwind readnone
>> +
>> +declare %divovf8  @llvm.safe.udiv.i8(i8, i8) nounwind readnone
>> +declare %divovf16 @llvm.safe.udiv.i16(i16, i16) nounwind readnone
>> +declare %divovf32 @llvm.safe.udiv.i32(i32, i32) nounwind readnone
>> +declare %divovf64 @llvm.safe.udiv.i64(i64, i64) nounwind readnone
>> +
>> +declare %divovf8  @llvm.safe.urem.i8(i8, i8) nounwind readnone
>> +declare %divovf16 @llvm.safe.urem.i16(i16, i16) nounwind readnone
>> +declare %divovf32 @llvm.safe.urem.i32(i32, i32) nounwind readnone
>> +declare %divovf64 @llvm.safe.urem.i64(i64, i64) nounwind readnone
>> +
>> +; CHECK-LABEL: sdiv8
>> +; CHECK: idivb{{[      ]}}
>> +define %divovf8 @sdiv8(i8 %x, i8 %y) {
>> +entry:
>> +  %divr = call %divovf8 @llvm.safe.sdiv.i8(i8 %x, i8 %y)
>> +  ret %divovf8 %divr
>> +}
>> +; CHECK-LABEL: sdiv16
>> +; CHECK: idivw{{[      ]}}
>> +define %divovf16 @sdiv16(i16 %x, i16 %y) {
>> +entry:
>> +  %divr = call %divovf16 @llvm.safe.sdiv.i16(i16 %x, i16 %y)
>> +  ret %divovf16 %divr
>> +}
>> +; CHECK-LABEL: sdiv32
>> +; CHECK: idivl{{[      ]}}
>> +define %divovf32 @sdiv32(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.sdiv.i32(i32 %x, i32 %y)
>> +  ret %divovf32 %divr
>> +}
>> +; CHECK-LABEL: sdiv64
>> +; CHECK: idivq{{[      ]}}
>> +define %divovf64 @sdiv64(i64 %x, i64 %y) {
>> +entry:
>> +  %divr = call %divovf64 @llvm.safe.sdiv.i64(i64 %x, i64 %y)
>> +  ret %divovf64 %divr
>> +}
>> +; CHECK-LABEL: udiv8
>> +; CHECK: {{[   ]}}divb{{[      ]}}
>> +define %divovf8 @udiv8(i8 %x, i8 %y) {
>> +entry:
>> +  %divr = call %divovf8 @llvm.safe.udiv.i8(i8 %x, i8 %y)
>> +  ret %divovf8 %divr
>> +}
>> +; CHECK-LABEL: udiv16
>> +; CHECK: {{[   ]}}divw{{[      ]}}
>> +define %divovf16 @udiv16(i16 %x, i16 %y) {
>> +entry:
>> +  %divr = call %divovf16 @llvm.safe.udiv.i16(i16 %x, i16 %y)
>> +  ret %divovf16 %divr
>> +}
>> +; CHECK-LABEL: udiv32
>> +; CHECK: {{[   ]}}divl{{[      ]}}
>> +define %divovf32 @udiv32(i32 %x, i32 %y) {
>> +entry:
>> +  %divr = call %divovf32 @llvm.safe.udiv.i32(i32 %x, i32 %y)
>> +  ret %divovf32 %divr
>> +}
>> +; CHECK-LABEL: udiv64
>> +; CHECK: {{[   ]}}divq{{[      ]}}
>> +define %divovf64 @udiv64(i64 %x, i64 %y) {
>> +entry:
>> +  %divr = call %divovf64 @llvm.safe.udiv.i64(i64 %x, i64 %y)
>> +  ret %divovf64 %divr
>> +}
>> +; CHECK-LABEL: srem8
>> +; CHECK: idivb{{[      ]}}
>> +define %divovf8 @srem8(i8 %x, i8 %y) {
>> +entry:
>> +  %remr = call %divovf8 @llvm.safe.srem.i8(i8 %x, i8 %y)
>> +  ret %divovf8 %remr
>> +}
>> +; CHECK-LABEL: srem16
>> +; CHECK: idivw{{[      ]}}
>> +define %divovf16 @srem16(i16 %x, i16 %y) {
>> +entry:
>> +  %remr = call %divovf16 @llvm.safe.srem.i16(i16 %x, i16 %y)
>> +  ret %divovf16 %remr
>> +}
>> +; CHECK-LABEL: srem32
>> +; CHECK: idivl{{[      ]}}
>> +define %divovf32 @srem32(i32 %x, i32 %y) {
>> +entry:
>> +  %remr = call %divovf32 @llvm.safe.srem.i32(i32 %x, i32 %y)
>> +  ret %divovf32 %remr
>> +}
>> +; CHECK-LABEL: srem64
>> +; CHECK: idivq{{[      ]}}
>> +define %divovf64 @srem64(i64 %x, i64 %y) {
>> +entry:
>> +  %remr = call %divovf64 @llvm.safe.srem.i64(i64 %x, i64 %y)
>> +  ret %divovf64 %remr
>> +}
>> +; CHECK-LABEL: urem8
>> +; CHECK: {{[   ]}}divb{{[      ]}}
>> +define %divovf8 @urem8(i8 %x, i8 %y) {
>> +entry:
>> +  %remr = call %divovf8 @llvm.safe.urem.i8(i8 %x, i8 %y)
>> +  ret %divovf8 %remr
>> +}
>> +; CHECK-LABEL: urem16
>> +; CHECK: {{[   ]}}divw{{[      ]}}
>> +define %divovf16 @urem16(i16 %x, i16 %y) {
>> +entry:
>> +  %remr = call %divovf16 @llvm.safe.urem.i16(i16 %x, i16 %y)
>> +  ret %divovf16 %remr
>> +}
>> +; CHECK-LABEL: urem32
>> +; CHECK: {{[   ]}}divl{{[      ]}}
>> +define %divovf32 @urem32(i32 %x, i32 %y) {
>> +entry:
>> +  %remr = call %divovf32 @llvm.safe.urem.i32(i32 %x, i32 %y)
>> +  ret %divovf32 %remr
>> +}
>> +; CHECK-LABEL: urem64
>> +; CHECK: {{[   ]}}divq{{[      ]}}
>> +define %divovf64 @urem64(i64 %x, i64 %y) {
>> +entry:
>> +  %remr = call %divovf64 @llvm.safe.urem.i64(i64 %x, i64 %y)
>> +  ret %divovf64 %remr
>> +}
>> +
>> +!llvm.ident = !{!0}
>> +
>> +!0 = metadata !{metadata !"clang version 3.5.0 "}
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140421/66775527/attachment.html>


More information about the llvm-commits mailing list