Index: llvm/trunk/lib/Target/ARM/ARMISelLowering.h =================================================================== --- llvm/trunk/lib/Target/ARM/ARMISelLowering.h +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.h @@ -467,6 +467,9 @@ bool canCombineStoreAndExtract(Type *VectorTy, Value *Idx, unsigned &Cost) const override; + bool isCheapToSpeculateCttz() const override; + bool isCheapToSpeculateCtlz() const override; + protected: std::pair findRepresentativeClass(const TargetRegisterInfo *TRI, Index: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp @@ -11841,6 +11841,14 @@ return false; } +bool ARMTargetLowering::isCheapToSpeculateCttz() const { + return Subtarget->hasV6T2Ops(); +} + +bool ARMTargetLowering::isCheapToSpeculateCtlz() const { + return Subtarget->hasV6T2Ops(); +} + Value *ARMTargetLowering::emitLoadLinked(IRBuilder<> &Builder, Value *Addr, AtomicOrdering Ord) const { Module *M = Builder.GetInsertBlock()->getParent()->getParent(); Index: llvm/trunk/test/Transforms/SimplifyCFG/ARM/cttz-ctlz.ll =================================================================== --- llvm/trunk/test/Transforms/SimplifyCFG/ARM/cttz-ctlz.ll +++ llvm/trunk/test/Transforms/SimplifyCFG/ARM/cttz-ctlz.ll @@ -0,0 +1,43 @@ +; RUN: opt -S -simplifycfg -mtriple=arm -mattr=+v6t2 < %s | FileCheck %s + +define i32 @ctlz(i32 %A) { +; CHECK-LABEL: @ctlz( +; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 +; CHECK-NEXT: [[CTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) +; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 32, i32 [[CTZ]] +; CHECK-NEXT: ret i32 [[SEL]] +entry: + %tobool = icmp eq i32 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: + %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) + br label %cond.end + +cond.end: + %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] + ret i32 %cond +} + +define i32 @cttz(i32 %A) { +; CHECK-LABEL: @cttz( +; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 +; CHECK-NEXT: [[CTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) +; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 32, i32 [[CTZ]] +; CHECK-NEXT: ret i32 [[SEL]] +entry: + %tobool = icmp eq i32 %A, 0 + br i1 %tobool, label %cond.end, label %cond.true + +cond.true: + %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) + br label %cond.end + +cond.end: + %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] + ret i32 %cond +} + +declare i32 @llvm.ctlz.i32(i32, i1) +declare i32 @llvm.cttz.i32(i32, i1) + Index: llvm/trunk/test/Transforms/SimplifyCFG/ARM/lit.local.cfg =================================================================== --- llvm/trunk/test/Transforms/SimplifyCFG/ARM/lit.local.cfg +++ llvm/trunk/test/Transforms/SimplifyCFG/ARM/lit.local.cfg @@ -0,0 +1,5 @@ +config.suffixes = ['.ll'] + +targets = set(config.root.targets_to_build.split()) +if not 'ARM' in targets: + config.unsupported = True