Index: llvm/trunk/include/llvm/IR/RuntimeLibcalls.def =================================================================== --- llvm/trunk/include/llvm/IR/RuntimeLibcalls.def +++ llvm/trunk/include/llvm/IR/RuntimeLibcalls.def @@ -83,6 +83,9 @@ HANDLE_LIBCALL(UDIVREM_I128, nullptr) HANDLE_LIBCALL(NEG_I32, "__negsi2") HANDLE_LIBCALL(NEG_I64, "__negdi2") +HANDLE_LIBCALL(CTLZ_I32, "__clzsi2") +HANDLE_LIBCALL(CTLZ_I64, "__clzdi2") +HANDLE_LIBCALL(CTLZ_I128, "__clzti2") // Floating-point HANDLE_LIBCALL(ADD_F32, "__addsf3") Index: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -4262,6 +4262,21 @@ RTLIB::MUL_I16, RTLIB::MUL_I32, RTLIB::MUL_I64, RTLIB::MUL_I128)); break; + case ISD::CTLZ_ZERO_UNDEF: + switch (Node->getSimpleValueType(0).SimpleTy) { + default: + llvm_unreachable("LibCall explicitly requested, but not available"); + case MVT::i32: + Results.push_back(ExpandLibCall(RTLIB::CTLZ_I32, Node, false)); + break; + case MVT::i64: + Results.push_back(ExpandLibCall(RTLIB::CTLZ_I64, Node, false)); + break; + case MVT::i128: + Results.push_back(ExpandLibCall(RTLIB::CTLZ_I128, Node, false)); + break; + } + break; } // Replace the original node with the legalized result. Index: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp @@ -850,8 +850,10 @@ } setOperationAction(ISD::CTTZ, MVT::i32, Custom); setOperationAction(ISD::CTPOP, MVT::i32, Expand); - if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) + if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) { setOperationAction(ISD::CTLZ, MVT::i32, Expand); + setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, LibCall); + } // @llvm.readcyclecounter requires the Performance Monitors extension. // Default to the 0 expansion on unsupported platforms. Index: llvm/trunk/test/CodeGen/ARM/clz.ll =================================================================== --- llvm/trunk/test/CodeGen/ARM/clz.ll +++ llvm/trunk/test/CodeGen/ARM/clz.ll @@ -1,10 +1,12 @@ -; RUN: llc -mtriple=arm-eabi -mattr=+v5t %s -o - | FileCheck %s +; RUN: llc -mtriple=arm-eabi -mattr=+v5t %s -o - | FileCheck %s -check-prefixes=CHECK,INLINE +; RUN: llc -mtriple=arm-eabi %s -o - | FileCheck %s -check-prefixes=CHECK,LIBCALL declare i32 @llvm.ctlz.i32(i32, i1) define i32 @test(i32 %x) { -; CHECK: test -; CHECK: clz r0, r0 +; CHECK-LABEL: test +; INLINE: clz r0, r0 +; LIBCALL: b __clzsi2 %tmp.1 = call i32 @llvm.ctlz.i32( i32 %x, i1 true ) ret i32 %tmp.1 }