Index: lib/CodeGen/CodeGenPrepare.cpp =================================================================== --- lib/CodeGen/CodeGenPrepare.cpp +++ lib/CodeGen/CodeGenPrepare.cpp @@ -4125,148 +4125,6 @@ Transition->setOperand(getTransitionOriginalValueIdx(), ToBePromoted); } -// See if we can speculate calls to intrinsic cttz/ctlz. -// -// Example: -// entry: -// ... -// %cmp = icmp eq i64 %val, 0 -// br i1 %cmp, label %end.bb, label %then.bb -// -// then.bb: -// %c = tail call i64 @llvm.cttz.i64(i64 %val, i1 true) -// br label %EndBB -// -// end.bb: -// %cond = phi i64 [ %c, %then.bb ], [ 64, %entry ] -// -// ==> -// -// entry: -// ... -// %c = tail call i64 @llvm.cttz.i64(i64 %val, i1 false) -// -static bool OptimizeBranchInst(BranchInst *BrInst, const TargetLowering &TLI) { - assert(BrInst->isConditional() && "Expected a conditional branch!"); - BasicBlock *ThenBB = BrInst->getSuccessor(1); - BasicBlock *EndBB = BrInst->getSuccessor(0); - - // See if ThenBB contains only one instruction (excluding the - // terminator and DbgInfoIntrinsic calls). - IntrinsicInst *II = nullptr; - CastInst *CI = nullptr; - for (BasicBlock::iterator I = ThenBB->begin(), - E = std::prev(ThenBB->end()); I != E; ++I) { - // Skip debug info. - if (isa(I)) - continue; - - // Check if this is a zero extension or a truncate of a previously - // matched call to intrinsic cttz/ctlz. - if (II) { - // Early exit if we already found a "free" zero extend/truncate. - if (CI) - return false; - - Type *SrcTy = II->getType(); - Type *DestTy = I->getType(); - Value *V; - - if (match(cast(I), m_ZExt(m_Value(V))) && V == II) { - // Speculate this zero extend only if it is "free" for the target. - if (TLI.isZExtFree(SrcTy, DestTy)) { - CI = cast(I); - continue; - } - } else if (match(cast(I), m_Trunc(m_Value(V))) && V == II) { - // Speculate this truncate only if it is "free" for the target. - if (TLI.isTruncateFree(SrcTy, DestTy)) { - CI = cast(I); - continue; - } - } else { - // Avoid speculating more than one instruction. - return false; - } - } - - // See if this is a call to intrinsic cttz/ctlz. - if (match(cast(I), m_Intrinsic())) { - // Avoid speculating expensive intrinsic calls. - if (!TLI.isCheapToSpeculateCttz()) - return false; - } - else if (match(cast(I), m_Intrinsic())) { - // Avoid speculating expensive intrinsic calls. - if (!TLI.isCheapToSpeculateCtlz()) - return false; - } else - return false; - - II = cast(I); - } - - // Look for PHI nodes with 'II' as the incoming value from 'ThenBB'. - BasicBlock *EntryBB = BrInst->getParent(); - for (BasicBlock::iterator I = EndBB->begin(); - PHINode *PN = dyn_cast(I); ++I) { - Value *ThenV = PN->getIncomingValueForBlock(ThenBB); - Value *OrigV = PN->getIncomingValueForBlock(EntryBB); - - if (!OrigV) - return false; - - if (ThenV != II && (!CI || ThenV != CI)) - return false; - - if (ConstantInt *CInt = dyn_cast(OrigV)) { - unsigned BitWidth = II->getType()->getIntegerBitWidth(); - - // Don't try to simplify this phi node if 'ThenV' is a cttz/ctlz - // intrinsic call, but 'OrigV' is not equal to the 'size-of' in bits - // of the value in input to the cttz/ctlz. - if (CInt->getValue() != BitWidth) - return false; - - // Hoist the call to cttz/ctlz from ThenBB into EntryBB. - EntryBB->getInstList().splice(BrInst, ThenBB->getInstList(), - ThenBB->begin(), std::prev(ThenBB->end())); - - // Update PN setting ThenV as the incoming value from both 'EntryBB' - // and 'ThenBB'. Eventually, method 'OptimizeInst' will fold this - // phi node if all the incoming values are the same. - PN->setIncomingValue(PN->getBasicBlockIndex(EntryBB), ThenV); - PN->setIncomingValue(PN->getBasicBlockIndex(ThenBB), ThenV); - - // Clear the 'undef on zero' flag of the cttz/ctlz intrinsic call. - if (cast(II->getArgOperand(1))->isOne()) { - Type *Ty = II->getArgOperand(0)->getType(); - Value *Args[] = { II->getArgOperand(0), - ConstantInt::getFalse(II->getContext()) }; - Module *M = EntryBB->getParent()->getParent(); - Value *IF = Intrinsic::getDeclaration(M, II->getIntrinsicID(), Ty); - IRBuilder<> Builder(II); - Instruction *NewI = Builder.CreateCall(IF, Args); - - // Replace the old call to cttz/ctlz. - II->replaceAllUsesWith(NewI); - II->eraseFromParent(); - } - - // Update BrInst condition so that the branch to EndBB is always taken. - // Later on, method 'ConstantFoldTerminator' will simplify this branch - // replacing it with a direct branch to 'EndBB'. - // As a side effect, CodeGenPrepare will attempt to simplify the control - // flow graph by deleting basic block 'ThenBB' and merging 'EntryBB' into - // 'EndBB' (calling method 'EliminateFallThrough'). - BrInst->setCondition(ConstantInt::getTrue(BrInst->getContext())); - return true; - } - } - - return false; -} - /// Some targets can do store(extractelement) with one instruction. /// Try to push the extractelement towards the stores when the target /// has this feature and this is profitable. @@ -4419,34 +4277,6 @@ if (isa(I)) return OptimizeExtractElementInst(I); - if (BranchInst *BI = dyn_cast(I)) { - if (TLI && BI->isConditional() && BI->getCondition()->hasOneUse()) { - // Check if the branch condition compares a value agaist zero. - if (ICmpInst *ICI = dyn_cast(BI->getCondition())) { - if (ICI->getPredicate() == ICmpInst::ICMP_EQ && - match(ICI->getOperand(1), m_Zero())) { - BasicBlock *ThenBB = BI->getSuccessor(1); - BasicBlock *EndBB = BI->getSuccessor(0); - - // Check if ThenBB is only reachable from this basic block; also, - // check if EndBB has more than one predecessor. - if (ThenBB->getSinglePredecessor() && - !EndBB->getSinglePredecessor()) { - TerminatorInst *TI = ThenBB->getTerminator(); - - if (TI->getNumSuccessors() == 1 && TI->getSuccessor(0) == EndBB && - // Try to speculate calls to intrinsic cttz/ctlz from 'ThenBB'. - OptimizeBranchInst(BI, *TLI)) { - ModifiedDT = true; - return true; - } - } - } - } - } - return false; - } - return false; } Index: test/CodeGen/PowerPC/cttz-ctlz-spec.ll =================================================================== --- test/CodeGen/PowerPC/cttz-ctlz-spec.ll +++ test/CodeGen/PowerPC/cttz-ctlz-spec.ll @@ -1,41 +0,0 @@ -; RUN: opt -S -codegenprepare < %s | FileCheck %s -target datalayout = "E-m:e-i64:64-n32:64" -target triple = "powerpc64-unknown-linux-gnu" - -define i64 @test1(i64 %A) { -; CHECK-LABEL: @test1( -; CHECK: [[CTLZ:%[A-Za-z0-9]+]] = call i64 @llvm.ctlz.i64(i64 %A, i1 false) -; CHECK-NEXT: ret i64 [[CTLZ]] -entry: - %tobool = icmp eq i64 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] - ret i64 %cond -} - -define i64 @test1b(i64 %A) { -; CHECK-LABEL: @test1b( -; CHECK: [[CTTZ:%[A-Za-z0-9]+]] = call i64 @llvm.cttz.i64(i64 %A, i1 false) -; CHECK-NEXT: ret i64 [[CTTZ]] -entry: - %tobool = icmp eq i64 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] - ret i64 %cond -} - -declare i64 @llvm.ctlz.i64(i64, i1) -declare i64 @llvm.cttz.i64(i64, i1) - Index: test/CodeGen/R600/cttz-ctlz.ll =================================================================== --- test/CodeGen/R600/cttz-ctlz.ll +++ test/CodeGen/R600/cttz-ctlz.ll @@ -1,225 +0,0 @@ -; RUN: opt -S -codegenprepare -mtriple=r600-unknown-unknown -mcpu=SI < %s | FileCheck -check-prefix=SI -check-prefix=ALL %s -; RUN: opt -S -codegenprepare -mtriple=r600-unknown-unknown -mcpu=tonga < %s | FileCheck -check-prefix=SI -check-prefix=ALL %s - - -define i64 @test1(i64 %A) { -; ALL-LABEL: @test1( -; SI: [[CTLZ:%[A-Za-z0-9]+]] = call i64 @llvm.ctlz.i64(i64 %A, i1 false) -; SI-NEXT: ret i64 [[CTLZ]] -entry: - %tobool = icmp eq i64 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] - ret i64 %cond -} - - -define i32 @test2(i32 %A) { -; ALL-LABEL: @test2( -; SI: [[CTLZ:%[A-Za-z0-9]+]] = call i32 @llvm.ctlz.i32(i32 %A, i1 false) -; SI-NEXT: ret i32 [[CTLZ]] -entry: - %tobool = icmp eq i32 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] - ret i32 %cond -} - - -define signext i16 @test3(i16 signext %A) { -; ALL-LABEL: @test3( -; SI: [[CTLZ:%[A-Za-z0-9]+]] = call i16 @llvm.ctlz.i16(i16 %A, i1 false) -; SI-NEXT: ret i16 [[CTLZ]] -entry: - %tobool = icmp eq i16 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ] - ret i16 %cond -} - - -define i64 @test1b(i64 %A) { -; ALL-LABEL: @test1b( -; SI: [[CTTZ:%[A-Za-z0-9]+]] = call i64 @llvm.cttz.i64(i64 %A, i1 false) -; SI-NEXT: ret i64 [[CTTZ]] -entry: - %tobool = icmp eq i64 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] - ret i64 %cond -} - - -define i32 @test2b(i32 %A) { -; ALL-LABEL: @test2b( -; SI: [[CTTZ:%[A-Za-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %A, i1 false) -; SI-NEXT: ret i32 [[CTTZ]] -entry: - %tobool = icmp eq i32 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] - ret i32 %cond -} - - -define signext i16 @test3b(i16 signext %A) { -; ALL-LABEL: @test3b( -; SI: [[CTTZ:%[A-Za-z0-9]+]] = call i16 @llvm.cttz.i16(i16 %A, i1 false) -; SI-NEXT: ret i16 [[CTTZ]] -entry: - %tobool = icmp eq i16 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ] - ret i16 %cond -} - - -define i64 @test1c(i64 %A) { -; ALL-LABEL: @test1c( -; ALL: icmp eq i64 %A, 0 -; ALL: call i64 @llvm.ctlz.i64(i64 %A, i1 true) -entry: - %tobool = icmp eq i64 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ] - ret i64 %cond -} - -define i32 @test2c(i32 %A) { -; ALL-LABEL: @test2c( -; ALL: icmp eq i32 %A, 0 -; ALL: call i32 @llvm.ctlz.i32(i32 %A, i1 true) -entry: - %tobool = icmp eq i32 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ] - ret i32 %cond -} - - -define signext i16 @test3c(i16 signext %A) { -; ALL-LABEL: @test3c( -; ALL: icmp eq i16 %A, 0 -; ALL: call i16 @llvm.ctlz.i16(i16 %A, i1 true) -entry: - %tobool = icmp eq i16 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ] - ret i16 %cond -} - - -define i64 @test1d(i64 %A) { -; ALL-LABEL: @test1d( -; ALL: icmp eq i64 %A, 0 -; ALL: call i64 @llvm.cttz.i64(i64 %A, i1 true) -entry: - %tobool = icmp eq i64 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ] - ret i64 %cond -} - - -define i32 @test2d(i32 %A) { -; ALL-LABEL: @test2d( -; ALL: icmp eq i32 %A, 0 -; ALL: call i32 @llvm.cttz.i32(i32 %A, i1 true) -entry: - %tobool = icmp eq i32 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ] - ret i32 %cond -} - - -define signext i16 @test3d(i16 signext %A) { -; ALL-LABEL: @test3d( -; ALL: icmp eq i16 %A, 0 -; ALL: call i16 @llvm.cttz.i16(i16 %A, i1 true) -entry: - %tobool = icmp eq i16 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ] - ret i16 %cond -} - - -declare i64 @llvm.ctlz.i64(i64, i1) -declare i32 @llvm.ctlz.i32(i32, i1) -declare i16 @llvm.ctlz.i16(i16, i1) -declare i64 @llvm.cttz.i64(i64, i1) -declare i32 @llvm.cttz.i32(i32, i1) -declare i16 @llvm.cttz.i16(i16, i1) Index: test/CodeGen/X86/cttz-ctlz.ll =================================================================== --- test/CodeGen/X86/cttz-ctlz.ll +++ test/CodeGen/X86/cttz-ctlz.ll @@ -1,422 +0,0 @@ -; RUN: opt -S -codegenprepare -mtriple=x86_64-unknown-unknown -mattr=+bmi < %s | FileCheck %s --check-prefix=ALL --check-prefix=BMI -; RUN: opt -S -codegenprepare -mtriple=x86_64-unknown-unknown -mattr=+lzcnt < %s | FileCheck %s --check-prefix=ALL --check-prefix=LZCNT -; RUN: opt -S -codegenprepare -mtriple=x86_64-unknown-unknown < %s | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC - - -define i64 @test1(i64 %A) { -; ALL-LABEL: @test1( -; LZCNT: [[CTLZ:%[A-Za-z0-9]+]] = call i64 @llvm.ctlz.i64(i64 %A, i1 false) -; LZCNT-NEXT: ret i64 [[CTLZ]] -; BMI: icmp eq i64 %A, 0 -; BMI: call i64 @llvm.ctlz.i64(i64 %A, i1 true) -; GENERIC: icmp eq i64 %A, 0 -; GENERIC: call i64 @llvm.ctlz.i64(i64 %A, i1 true) -entry: - %tobool = icmp eq i64 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] - ret i64 %cond -} - - -define i32 @test2(i32 %A) { -; ALL-LABEL: @test2( -; LZCNT: [[CTLZ:%[A-Za-z0-9]+]] = call i32 @llvm.ctlz.i32(i32 %A, i1 false) -; LZCNT-NEXT: ret i32 [[CTLZ]] -; BMI: icmp eq i32 %A, 0 -; BMI: call i32 @llvm.ctlz.i32(i32 %A, i1 true) -; GENERIC: icmp eq i32 %A, 0 -; GENERIC: call i32 @llvm.ctlz.i32(i32 %A, i1 true) -entry: - %tobool = icmp eq i32 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] - ret i32 %cond -} - - -define signext i16 @test3(i16 signext %A) { -; ALL-LABEL: @test3( -; LZCNT: [[CTLZ:%[A-Za-z0-9]+]] = call i16 @llvm.ctlz.i16(i16 %A, i1 false) -; LZCNT-NEXT: ret i16 [[CTLZ]] -; BMI: icmp eq i16 %A, 0 -; BMI: call i16 @llvm.ctlz.i16(i16 %A, i1 true) -; GENERIC: icmp eq i16 %A, 0 -; GENERIC: call i16 @llvm.ctlz.i16(i16 %A, i1 true) -entry: - %tobool = icmp eq i16 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ] - ret i16 %cond -} - - -define i64 @test1b(i64 %A) { -; ALL-LABEL: @test1b( -; LZCNT: icmp eq i64 %A, 0 -; LZCNT: call i64 @llvm.cttz.i64(i64 %A, i1 true) -; BMI: [[CTTZ:%[A-Za-z0-9]+]] = call i64 @llvm.cttz.i64(i64 %A, i1 false) -; BMI-NEXT: ret i64 [[CTTZ]] -; GENERIC: icmp eq i64 %A, 0 -; GENERIC: call i64 @llvm.cttz.i64(i64 %A, i1 true) -entry: - %tobool = icmp eq i64 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] - ret i64 %cond -} - - -define i32 @test2b(i32 %A) { -; ALL-LABEL: @test2b( -; LZCNT: icmp eq i32 %A, 0 -; LZCNT: call i32 @llvm.cttz.i32(i32 %A, i1 true) -; BMI: [[CTTZ:%[A-Za-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %A, i1 false) -; BMI-NEXT: ret i32 [[CTTZ]] -; GENERIC: icmp eq i32 %A, 0 -; GENERIC: call i32 @llvm.cttz.i32(i32 %A, i1 true) -entry: - %tobool = icmp eq i32 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] - ret i32 %cond -} - - -define signext i16 @test3b(i16 signext %A) { -; ALL-LABEL: @test3b( -; LZCNT: icmp eq i16 %A, 0 -; LZCNT: call i16 @llvm.cttz.i16(i16 %A, i1 true) -; BMI: [[CTTZ:%[A-Za-z0-9]+]] = call i16 @llvm.cttz.i16(i16 %A, i1 false) -; BMI-NEXT: ret i16 [[CTTZ]] -; GENERIC: icmp eq i16 %A, 0 -; GENERIC: call i16 @llvm.cttz.i16(i16 %A, i1 true) -entry: - %tobool = icmp eq i16 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ] - ret i16 %cond -} - - -define i64 @test1c(i64 %A) { -; ALL-LABEL: @test1c( -; ALL: icmp eq i64 %A, 0 -; ALL: call i64 @llvm.ctlz.i64(i64 %A, i1 true) -entry: - %tobool = icmp eq i64 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ] - ret i64 %cond -} - -define i32 @test2c(i32 %A) { -; ALL-LABEL: @test2c( -; ALL: icmp eq i32 %A, 0 -; ALL: call i32 @llvm.ctlz.i32(i32 %A, i1 true) -entry: - %tobool = icmp eq i32 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ] - ret i32 %cond -} - - -define signext i16 @test3c(i16 signext %A) { -; ALL-LABEL: @test3c( -; ALL: icmp eq i16 %A, 0 -; ALL: call i16 @llvm.ctlz.i16(i16 %A, i1 true) -entry: - %tobool = icmp eq i16 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ] - ret i16 %cond -} - - -define i64 @test1d(i64 %A) { -; ALL-LABEL: @test1d( -; ALL: icmp eq i64 %A, 0 -; ALL: call i64 @llvm.cttz.i64(i64 %A, i1 true) -entry: - %tobool = icmp eq i64 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ] - ret i64 %cond -} - - -define i32 @test2d(i32 %A) { -; ALL-LABEL: @test2d( -; ALL: icmp eq i32 %A, 0 -; ALL: call i32 @llvm.cttz.i32(i32 %A, i1 true) -entry: - %tobool = icmp eq i32 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ] - ret i32 %cond -} - - -define signext i16 @test3d(i16 signext %A) { -; ALL-LABEL: @test3d( -; ALL: icmp eq i16 %A, 0 -; ALL: call i16 @llvm.cttz.i16(i16 %A, i1 true) -entry: - %tobool = icmp eq i16 %A, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ] - ret i16 %cond -} - -; The following tests verify that calls to cttz/ctlz are speculated even if -; basic block %cond.true has an extra zero extend/truncate which is "free" -; for the target. - -define i64 @test1e(i32 %x) { -; ALL-LABEL: @test1e( -; LZCNT: icmp eq i32 %x, 0 -; LZCNT: call i32 @llvm.cttz.i32(i32 %x, i1 true) -; BMI: call i32 @llvm.cttz.i32(i32 %x, i1 false) -; GENERIC: icmp eq i32 %x, 0 -; GENERIC: call i32 @llvm.cttz.i32(i32 %x, i1 true) -entry: - %tobool = icmp eq i32 %x, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) - %phitmp2 = zext i32 %0 to i64 - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ] - ret i64 %cond -} - -define i32 @test2e(i64 %x) { -; ALL-LABEL: @test2e( -; LZCNT: icmp eq i64 %x, 0 -; LZCNT: call i64 @llvm.cttz.i64(i64 %x, i1 true) -; BMI: call i64 @llvm.cttz.i64(i64 %x, i1 false) -; GENERIC: icmp eq i64 %x, 0 -; GENERIC: call i64 @llvm.cttz.i64(i64 %x, i1 true) -entry: - %tobool = icmp eq i64 %x, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) - %cast = trunc i64 %0 to i32 - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ] - ret i32 %cond -} - -define i64 @test3e(i32 %x) { -; ALL-LABEL: @test3e( -; BMI: icmp eq i32 %x, 0 -; BMI: call i32 @llvm.ctlz.i32(i32 %x, i1 true) -; LZCNT: call i32 @llvm.ctlz.i32(i32 %x, i1 false) -; GENERIC: icmp eq i32 %x, 0 -; GENERIC: call i32 @llvm.ctlz.i32(i32 %x, i1 true) -entry: - %tobool = icmp eq i32 %x, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) - %phitmp2 = zext i32 %0 to i64 - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ] - ret i64 %cond -} - -define i32 @test4e(i64 %x) { -; ALL-LABEL: @test4e( -; BMI: icmp eq i64 %x, 0 -; BMI: call i64 @llvm.ctlz.i64(i64 %x, i1 true) -; LZCNT: call i64 @llvm.ctlz.i64(i64 %x, i1 false) -; GENERIC: icmp eq i64 %x, 0 -; GENERIC: call i64 @llvm.ctlz.i64(i64 %x, i1 true) -entry: - %tobool = icmp eq i64 %x, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) - %cast = trunc i64 %0 to i32 - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ] - ret i32 %cond -} - -define i16 @test5e(i64 %x) { -; ALL-LABEL: @test5e( -; BMI: icmp eq i64 %x, 0 -; BMI: call i64 @llvm.ctlz.i64(i64 %x, i1 true) -; LZCNT: call i64 @llvm.ctlz.i64(i64 %x, i1 false) -; GENERIC: icmp eq i64 %x, 0 -; GENERIC: call i64 @llvm.ctlz.i64(i64 %x, i1 true) -entry: - %tobool = icmp eq i64 %x, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) - %cast = trunc i64 %0 to i16 - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ] - ret i16 %cond -} - -define i16 @test6e(i32 %x) { -; ALL-LABEL: @test6e( -; BMI: icmp eq i32 %x, 0 -; BMI: call i32 @llvm.ctlz.i32(i32 %x, i1 true) -; LZCNT: call i32 @llvm.ctlz.i32(i32 %x, i1 false) -; GENERIC: icmp eq i32 %x, 0 -; GENERIC: call i32 @llvm.ctlz.i32(i32 %x, i1 true) -entry: - %tobool = icmp eq i32 %x, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) - %cast = trunc i32 %0 to i16 - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ] - ret i16 %cond -} - -define i16 @test7e(i64 %x) { -; ALL-LABEL: @test7e( -; LZCNT: icmp eq i64 %x, 0 -; LZCNT: call i64 @llvm.cttz.i64(i64 %x, i1 true) -; BMI: call i64 @llvm.cttz.i64(i64 %x, i1 false) -; GENERIC: icmp eq i64 %x, 0 -; GENERIC: call i64 @llvm.cttz.i64(i64 %x, i1 true) -entry: - %tobool = icmp eq i64 %x, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) - %cast = trunc i64 %0 to i16 - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ] - ret i16 %cond -} - -define i16 @test8e(i32 %x) { -; ALL-LABEL: @test8e( -; LZCNT: icmp eq i32 %x, 0 -; LZCNT: call i32 @llvm.cttz.i32(i32 %x, i1 true) -; BMI: call i32 @llvm.cttz.i32(i32 %x, i1 false) -; GENERIC: icmp eq i32 %x, 0 -; GENERIC: call i32 @llvm.cttz.i32(i32 %x, i1 true) -entry: - %tobool = icmp eq i32 %x, 0 - br i1 %tobool, label %cond.end, label %cond.true - -cond.true: ; preds = %entry - %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) - %cast = trunc i32 %0 to i16 - br label %cond.end - -cond.end: ; preds = %entry, %cond.true - %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ] - ret i16 %cond -} - - -declare i64 @llvm.ctlz.i64(i64, i1) -declare i32 @llvm.ctlz.i32(i32, i1) -declare i16 @llvm.ctlz.i16(i16, i1) -declare i64 @llvm.cttz.i64(i64, i1) -declare i32 @llvm.cttz.i32(i32, i1) -declare i16 @llvm.cttz.i16(i16, i1) Index: test/Transforms/SimplifyCFG/PowerPC/cttz-ctlz-spec.ll =================================================================== --- test/Transforms/SimplifyCFG/PowerPC/cttz-ctlz-spec.ll +++ test/Transforms/SimplifyCFG/PowerPC/cttz-ctlz-spec.ll @@ -0,0 +1,45 @@ +; RUN: opt -S -simplifycfg < %s | FileCheck %s +target datalayout = "E-m:e-i64:64-n32:64" +target triple = "powerpc64-unknown-linux-gnu" + +define i64 @test1(i64 %A) { +; CHECK-LABEL: @test1( +; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 +; CHECK-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) +; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 64, i64 [[CTLZ]] +; CHECK-NEXT: ret i64 [[SEL]] +entry: + %tobool = icmp eq i64 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] + ret i64 %cond +} + +define i64 @test1b(i64 %A) { +; CHECK-LABEL: @test1b( +; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 +; CHECK-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) +; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 64, i64 [[CTLZ]] +; CHECK-NEXT: ret i64 [[SEL]] +entry: + %tobool = icmp eq i64 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] + ret i64 %cond +} + +declare i64 @llvm.ctlz.i64(i64, i1) +declare i64 @llvm.cttz.i64(i64, i1) + Index: test/Transforms/SimplifyCFG/PowerPC/lit.local.cfg =================================================================== --- test/Transforms/SimplifyCFG/PowerPC/lit.local.cfg +++ test/Transforms/SimplifyCFG/PowerPC/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'PowerPC' in config.root.targets: + config.unsupported = True Index: test/Transforms/SimplifyCFG/R600/cttz-ctlz.ll =================================================================== --- test/Transforms/SimplifyCFG/R600/cttz-ctlz.ll +++ test/Transforms/SimplifyCFG/R600/cttz-ctlz.ll @@ -0,0 +1,249 @@ +; RUN: opt -S -simplifycfg -mtriple=r600-unknown-unknown -mcpu=SI < %s | FileCheck -check-prefix=SI -check-prefix=ALL %s +; RUN: opt -S -simplifycfg -mtriple=r600-unknown-unknown -mcpu=tonga < %s | FileCheck -check-prefix=SI -check-prefix=ALL %s + + +define i64 @test1(i64 %A) { +; ALL-LABEL: @test1( +; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 +; SI-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) +; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 64, i64 [[CTLZ]] +; SI-NEXT: ret i64 [[SEL]] +entry: + %tobool = icmp eq i64 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] + ret i64 %cond +} + + +define i32 @test2(i32 %A) { +; ALL-LABEL: @test2( +; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 +; SI-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) +; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 32, i32 [[CTLZ]] +; SI-NEXT: ret i32 [[SEL]] +entry: + %tobool = icmp eq i32 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] + ret i32 %cond +} + + +define signext i16 @test3(i16 signext %A) { +; ALL-LABEL: @test3( +; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0 +; SI-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) +; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i16 16, i16 [[CTLZ]] +; SI-NEXT: ret i16 [[SEL]] +entry: + %tobool = icmp eq i16 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ] + ret i16 %cond +} + + +define i64 @test1b(i64 %A) { +; ALL-LABEL: @test1b( +; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 +; SI-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) +; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 64, i64 [[CTTZ]] +; SI-NEXT: ret i64 [[SEL]] +entry: + %tobool = icmp eq i64 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] + ret i64 %cond +} + + +define i32 @test2b(i32 %A) { +; ALL-LABEL: @test2b( +; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 +; SI-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) +; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 32, i32 [[CTTZ]] +; SI-NEXT: ret i32 [[SEL]] +entry: + %tobool = icmp eq i32 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] + ret i32 %cond +} + + +define signext i16 @test3b(i16 signext %A) { +; ALL-LABEL: @test3b( +; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0 +; SI-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) +; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i16 16, i16 [[CTTZ]] +; SI-NEXT: ret i16 [[SEL]] +entry: + %tobool = icmp eq i16 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ] + ret i16 %cond +} + + +define i64 @test1c(i64 %A) { +; ALL-LABEL: @test1c( +; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 +; ALL-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) +; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 63, i64 [[CTLZ]] +; ALL-NEXT: ret i64 [[SEL]] +entry: + %tobool = icmp eq i64 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ] + ret i64 %cond +} + +define i32 @test2c(i32 %A) { +; ALL-LABEL: @test2c( +; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 +; ALL-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) +; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 31, i32 [[CTLZ]] +; ALL-NEXT: ret i32 [[SEL]] +entry: + %tobool = icmp eq i32 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ] + ret i32 %cond +} + + +define signext i16 @test3c(i16 signext %A) { +; ALL-LABEL: @test3c( +; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0 +; ALL-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) +; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i16 15, i16 [[CTLZ]] +; ALL-NEXT: ret i16 [[SEL]] +entry: + %tobool = icmp eq i16 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ] + ret i16 %cond +} + + +define i64 @test1d(i64 %A) { +; ALL-LABEL: @test1d( +; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 +; ALL-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) +; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 63, i64 [[CTTZ]] +; ALL-NEXT: ret i64 [[SEL]] +entry: + %tobool = icmp eq i64 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ] + ret i64 %cond +} + + +define i32 @test2d(i32 %A) { +; ALL-LABEL: @test2d( +; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 +; ALL-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) +; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 31, i32 [[CTTZ]] +; ALL-NEXT: ret i32 [[SEL]] +entry: + %tobool = icmp eq i32 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ] + ret i32 %cond +} + + +define signext i16 @test3d(i16 signext %A) { +; ALL-LABEL: @test3d( +; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0 +; ALL-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) +; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i16 15, i16 [[CTTZ]] +; ALL-NEXT: ret i16 [[SEL]] +entry: + %tobool = icmp eq i16 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: ; preds = %entry + %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) + br label %cond.end + +cond.end: ; preds = %entry, %cond.true + %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ] + ret i16 %cond +} + + +declare i64 @llvm.ctlz.i64(i64, i1) +declare i32 @llvm.ctlz.i32(i32, i1) +declare i16 @llvm.ctlz.i16(i16, i1) +declare i64 @llvm.cttz.i64(i64, i1) +declare i32 @llvm.cttz.i32(i32, i1) +declare i16 @llvm.cttz.i16(i16, i1) Index: test/Transforms/SimplifyCFG/R600/lit.local.cfg =================================================================== --- test/Transforms/SimplifyCFG/R600/lit.local.cfg +++ test/Transforms/SimplifyCFG/R600/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'R600' in config.root.targets: + config.unsupported = True