mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-09 13:55:22 +00:00
[CodeGenPrepare] Removed duplicate logic. SimplifyCFG already knows how to speculate calls to cttz/ctlz.
SimplifyCFG now knows how to speculate calls to intrinsic cttz/ctlz that are 'cheap' for the target. Therefore, some of the logic in CodeGenPrepare that was originally added at revision 224899 can now be removed. This patch is basically a no functional change. It removes the duplicated logic in CodeGenPrepare and converts all the existing target specific tests for cttz/ctlz into SimplifyCFG tests. Differential Revision: http://reviews.llvm.org/D7608 llvm-svn: 229105
This commit is contained in:
parent
b1fde3b904
commit
7791371c4e
@ -4125,148 +4125,6 @@ void VectorPromoteHelper::promoteImpl(Instruction *ToBePromoted) {
|
|||||||
Transition->setOperand(getTransitionOriginalValueIdx(), ToBePromoted);
|
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<DbgInfoIntrinsic>(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<Instruction>(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<CastInst>(I);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else if (match(cast<Instruction>(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<CastInst>(I);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Avoid speculating more than one instruction.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if this is a call to intrinsic cttz/ctlz.
|
|
||||||
if (match(cast<Instruction>(I), m_Intrinsic<Intrinsic::cttz>())) {
|
|
||||||
// Avoid speculating expensive intrinsic calls.
|
|
||||||
if (!TLI.isCheapToSpeculateCttz())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (match(cast<Instruction>(I), m_Intrinsic<Intrinsic::ctlz>())) {
|
|
||||||
// Avoid speculating expensive intrinsic calls.
|
|
||||||
if (!TLI.isCheapToSpeculateCtlz())
|
|
||||||
return false;
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
II = cast<IntrinsicInst>(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<PHINode>(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<ConstantInt>(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<ConstantInt>(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.
|
/// Some targets can do store(extractelement) with one instruction.
|
||||||
/// Try to push the extractelement towards the stores when the target
|
/// Try to push the extractelement towards the stores when the target
|
||||||
/// has this feature and this is profitable.
|
/// has this feature and this is profitable.
|
||||||
@ -4419,34 +4277,6 @@ bool CodeGenPrepare::OptimizeInst(Instruction *I, bool& ModifiedDT) {
|
|||||||
if (isa<ExtractElementInst>(I))
|
if (isa<ExtractElementInst>(I))
|
||||||
return OptimizeExtractElementInst(I);
|
return OptimizeExtractElementInst(I);
|
||||||
|
|
||||||
if (BranchInst *BI = dyn_cast<BranchInst>(I)) {
|
|
||||||
if (TLI && BI->isConditional() && BI->getCondition()->hasOneUse()) {
|
|
||||||
// Check if the branch condition compares a value agaist zero.
|
|
||||||
if (ICmpInst *ICI = dyn_cast<ICmpInst>(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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
|
@ -1,11 +1,13 @@
|
|||||||
; RUN: opt -S -codegenprepare < %s | FileCheck %s
|
; RUN: opt -S -simplifycfg < %s | FileCheck %s
|
||||||
target datalayout = "E-m:e-i64:64-n32:64"
|
target datalayout = "E-m:e-i64:64-n32:64"
|
||||||
target triple = "powerpc64-unknown-linux-gnu"
|
target triple = "powerpc64-unknown-linux-gnu"
|
||||||
|
|
||||||
define i64 @test1(i64 %A) {
|
define i64 @test1(i64 %A) {
|
||||||
; CHECK-LABEL: @test1(
|
; CHECK-LABEL: @test1(
|
||||||
; CHECK: [[CTLZ:%[A-Za-z0-9]+]] = call i64 @llvm.ctlz.i64(i64 %A, i1 false)
|
; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
|
||||||
; CHECK-NEXT: ret i64 [[CTLZ]]
|
; 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:
|
entry:
|
||||||
%tobool = icmp eq i64 %A, 0
|
%tobool = icmp eq i64 %A, 0
|
||||||
br i1 %tobool, label %cond.end, label %cond.true
|
br i1 %tobool, label %cond.end, label %cond.true
|
||||||
@ -21,8 +23,10 @@ cond.end: ; preds = %entry, %cond.true
|
|||||||
|
|
||||||
define i64 @test1b(i64 %A) {
|
define i64 @test1b(i64 %A) {
|
||||||
; CHECK-LABEL: @test1b(
|
; CHECK-LABEL: @test1b(
|
||||||
; CHECK: [[CTTZ:%[A-Za-z0-9]+]] = call i64 @llvm.cttz.i64(i64 %A, i1 false)
|
; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
|
||||||
; CHECK-NEXT: ret i64 [[CTTZ]]
|
; 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:
|
entry:
|
||||||
%tobool = icmp eq i64 %A, 0
|
%tobool = icmp eq i64 %A, 0
|
||||||
br i1 %tobool, label %cond.end, label %cond.true
|
br i1 %tobool, label %cond.end, label %cond.true
|
2
test/Transforms/SimplifyCFG/PowerPC/lit.local.cfg
Normal file
2
test/Transforms/SimplifyCFG/PowerPC/lit.local.cfg
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
if not 'PowerPC' in config.root.targets:
|
||||||
|
config.unsupported = True
|
@ -1,11 +1,13 @@
|
|||||||
; RUN: opt -S -codegenprepare -mtriple=r600-unknown-unknown -mcpu=SI < %s | FileCheck -check-prefix=SI -check-prefix=ALL %s
|
; RUN: opt -S -simplifycfg -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
|
; RUN: opt -S -simplifycfg -mtriple=r600-unknown-unknown -mcpu=tonga < %s | FileCheck -check-prefix=SI -check-prefix=ALL %s
|
||||||
|
|
||||||
|
|
||||||
define i64 @test1(i64 %A) {
|
define i64 @test1(i64 %A) {
|
||||||
; ALL-LABEL: @test1(
|
; ALL-LABEL: @test1(
|
||||||
; SI: [[CTLZ:%[A-Za-z0-9]+]] = call i64 @llvm.ctlz.i64(i64 %A, i1 false)
|
; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
|
||||||
; SI-NEXT: ret i64 [[CTLZ]]
|
; 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:
|
entry:
|
||||||
%tobool = icmp eq i64 %A, 0
|
%tobool = icmp eq i64 %A, 0
|
||||||
br i1 %tobool, label %cond.end, label %cond.true
|
br i1 %tobool, label %cond.end, label %cond.true
|
||||||
@ -22,8 +24,10 @@ cond.end: ; preds = %entry, %cond.true
|
|||||||
|
|
||||||
define i32 @test2(i32 %A) {
|
define i32 @test2(i32 %A) {
|
||||||
; ALL-LABEL: @test2(
|
; ALL-LABEL: @test2(
|
||||||
; SI: [[CTLZ:%[A-Za-z0-9]+]] = call i32 @llvm.ctlz.i32(i32 %A, i1 false)
|
; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
|
||||||
; SI-NEXT: ret i32 [[CTLZ]]
|
; 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:
|
entry:
|
||||||
%tobool = icmp eq i32 %A, 0
|
%tobool = icmp eq i32 %A, 0
|
||||||
br i1 %tobool, label %cond.end, label %cond.true
|
br i1 %tobool, label %cond.end, label %cond.true
|
||||||
@ -40,8 +44,10 @@ cond.end: ; preds = %entry, %cond.true
|
|||||||
|
|
||||||
define signext i16 @test3(i16 signext %A) {
|
define signext i16 @test3(i16 signext %A) {
|
||||||
; ALL-LABEL: @test3(
|
; ALL-LABEL: @test3(
|
||||||
; SI: [[CTLZ:%[A-Za-z0-9]+]] = call i16 @llvm.ctlz.i16(i16 %A, i1 false)
|
; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0
|
||||||
; SI-NEXT: ret i16 [[CTLZ]]
|
; 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:
|
entry:
|
||||||
%tobool = icmp eq i16 %A, 0
|
%tobool = icmp eq i16 %A, 0
|
||||||
br i1 %tobool, label %cond.end, label %cond.true
|
br i1 %tobool, label %cond.end, label %cond.true
|
||||||
@ -58,8 +64,10 @@ cond.end: ; preds = %entry, %cond.true
|
|||||||
|
|
||||||
define i64 @test1b(i64 %A) {
|
define i64 @test1b(i64 %A) {
|
||||||
; ALL-LABEL: @test1b(
|
; ALL-LABEL: @test1b(
|
||||||
; SI: [[CTTZ:%[A-Za-z0-9]+]] = call i64 @llvm.cttz.i64(i64 %A, i1 false)
|
; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
|
||||||
; SI-NEXT: ret i64 [[CTTZ]]
|
; 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:
|
entry:
|
||||||
%tobool = icmp eq i64 %A, 0
|
%tobool = icmp eq i64 %A, 0
|
||||||
br i1 %tobool, label %cond.end, label %cond.true
|
br i1 %tobool, label %cond.end, label %cond.true
|
||||||
@ -76,8 +84,10 @@ cond.end: ; preds = %entry, %cond.true
|
|||||||
|
|
||||||
define i32 @test2b(i32 %A) {
|
define i32 @test2b(i32 %A) {
|
||||||
; ALL-LABEL: @test2b(
|
; ALL-LABEL: @test2b(
|
||||||
; SI: [[CTTZ:%[A-Za-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %A, i1 false)
|
; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
|
||||||
; SI-NEXT: ret i32 [[CTTZ]]
|
; 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:
|
entry:
|
||||||
%tobool = icmp eq i32 %A, 0
|
%tobool = icmp eq i32 %A, 0
|
||||||
br i1 %tobool, label %cond.end, label %cond.true
|
br i1 %tobool, label %cond.end, label %cond.true
|
||||||
@ -94,8 +104,10 @@ cond.end: ; preds = %entry, %cond.true
|
|||||||
|
|
||||||
define signext i16 @test3b(i16 signext %A) {
|
define signext i16 @test3b(i16 signext %A) {
|
||||||
; ALL-LABEL: @test3b(
|
; ALL-LABEL: @test3b(
|
||||||
; SI: [[CTTZ:%[A-Za-z0-9]+]] = call i16 @llvm.cttz.i16(i16 %A, i1 false)
|
; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0
|
||||||
; SI-NEXT: ret i16 [[CTTZ]]
|
; 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:
|
entry:
|
||||||
%tobool = icmp eq i16 %A, 0
|
%tobool = icmp eq i16 %A, 0
|
||||||
br i1 %tobool, label %cond.end, label %cond.true
|
br i1 %tobool, label %cond.end, label %cond.true
|
||||||
@ -112,8 +124,10 @@ cond.end: ; preds = %entry, %cond.true
|
|||||||
|
|
||||||
define i64 @test1c(i64 %A) {
|
define i64 @test1c(i64 %A) {
|
||||||
; ALL-LABEL: @test1c(
|
; ALL-LABEL: @test1c(
|
||||||
; ALL: icmp eq i64 %A, 0
|
; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
|
||||||
; ALL: call i64 @llvm.ctlz.i64(i64 %A, i1 true)
|
; 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:
|
entry:
|
||||||
%tobool = icmp eq i64 %A, 0
|
%tobool = icmp eq i64 %A, 0
|
||||||
br i1 %tobool, label %cond.end, label %cond.true
|
br i1 %tobool, label %cond.end, label %cond.true
|
||||||
@ -129,8 +143,10 @@ cond.end: ; preds = %entry, %cond.true
|
|||||||
|
|
||||||
define i32 @test2c(i32 %A) {
|
define i32 @test2c(i32 %A) {
|
||||||
; ALL-LABEL: @test2c(
|
; ALL-LABEL: @test2c(
|
||||||
; ALL: icmp eq i32 %A, 0
|
; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
|
||||||
; ALL: call i32 @llvm.ctlz.i32(i32 %A, i1 true)
|
; 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:
|
entry:
|
||||||
%tobool = icmp eq i32 %A, 0
|
%tobool = icmp eq i32 %A, 0
|
||||||
br i1 %tobool, label %cond.end, label %cond.true
|
br i1 %tobool, label %cond.end, label %cond.true
|
||||||
@ -147,8 +163,10 @@ cond.end: ; preds = %entry, %cond.true
|
|||||||
|
|
||||||
define signext i16 @test3c(i16 signext %A) {
|
define signext i16 @test3c(i16 signext %A) {
|
||||||
; ALL-LABEL: @test3c(
|
; ALL-LABEL: @test3c(
|
||||||
; ALL: icmp eq i16 %A, 0
|
; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0
|
||||||
; ALL: call i16 @llvm.ctlz.i16(i16 %A, i1 true)
|
; 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:
|
entry:
|
||||||
%tobool = icmp eq i16 %A, 0
|
%tobool = icmp eq i16 %A, 0
|
||||||
br i1 %tobool, label %cond.end, label %cond.true
|
br i1 %tobool, label %cond.end, label %cond.true
|
||||||
@ -165,8 +183,10 @@ cond.end: ; preds = %entry, %cond.true
|
|||||||
|
|
||||||
define i64 @test1d(i64 %A) {
|
define i64 @test1d(i64 %A) {
|
||||||
; ALL-LABEL: @test1d(
|
; ALL-LABEL: @test1d(
|
||||||
; ALL: icmp eq i64 %A, 0
|
; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
|
||||||
; ALL: call i64 @llvm.cttz.i64(i64 %A, i1 true)
|
; 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:
|
entry:
|
||||||
%tobool = icmp eq i64 %A, 0
|
%tobool = icmp eq i64 %A, 0
|
||||||
br i1 %tobool, label %cond.end, label %cond.true
|
br i1 %tobool, label %cond.end, label %cond.true
|
||||||
@ -183,8 +203,10 @@ cond.end: ; preds = %entry, %cond.true
|
|||||||
|
|
||||||
define i32 @test2d(i32 %A) {
|
define i32 @test2d(i32 %A) {
|
||||||
; ALL-LABEL: @test2d(
|
; ALL-LABEL: @test2d(
|
||||||
; ALL: icmp eq i32 %A, 0
|
; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
|
||||||
; ALL: call i32 @llvm.cttz.i32(i32 %A, i1 true)
|
; 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:
|
entry:
|
||||||
%tobool = icmp eq i32 %A, 0
|
%tobool = icmp eq i32 %A, 0
|
||||||
br i1 %tobool, label %cond.end, label %cond.true
|
br i1 %tobool, label %cond.end, label %cond.true
|
||||||
@ -201,8 +223,10 @@ cond.end: ; preds = %entry, %cond.true
|
|||||||
|
|
||||||
define signext i16 @test3d(i16 signext %A) {
|
define signext i16 @test3d(i16 signext %A) {
|
||||||
; ALL-LABEL: @test3d(
|
; ALL-LABEL: @test3d(
|
||||||
; ALL: icmp eq i16 %A, 0
|
; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0
|
||||||
; ALL: call i16 @llvm.cttz.i16(i16 %A, i1 true)
|
; 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:
|
entry:
|
||||||
%tobool = icmp eq i16 %A, 0
|
%tobool = icmp eq i16 %A, 0
|
||||||
br i1 %tobool, label %cond.end, label %cond.true
|
br i1 %tobool, label %cond.end, label %cond.true
|
2
test/Transforms/SimplifyCFG/R600/lit.local.cfg
Normal file
2
test/Transforms/SimplifyCFG/R600/lit.local.cfg
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
if not 'R600' in config.root.targets:
|
||||||
|
config.unsupported = True
|
Loading…
x
Reference in New Issue
Block a user