Index: lib/Target/NDS32/NDS32InstrFormats.td =================================================================== --- lib/Target/NDS32/NDS32InstrFormats.td +++ lib/Target/NDS32/NDS32InstrFormats.td @@ -66,6 +66,17 @@ let Inst{5-0} = sub_opcode; } +class ALU_2Form_r pattern, + bits<6> sub_opcode> + : 32BitInst<0b100001, outs, ins, asmstr, pattern> { + bits<5> Rt; + bits<5> Ra; + let Inst{24-20} = Rt; + let Inst{19-15} = Ra; + let Inst{14-6} = 0; + let Inst{5-0} = sub_opcode; +} + class 32Bit_5R5R15Imm opcode, dag outs, dag ins, string asmstr, list pattern> : 32BitInst { Index: lib/Target/NDS32/NDS32InstrInfo.td =================================================================== --- lib/Target/NDS32/NDS32InstrInfo.td +++ lib/Target/NDS32/NDS32InstrInfo.td @@ -303,6 +303,16 @@ //===----------------------------------------------------------------------===// +// Performance Extension Instructions +// + +def CLZ : ALU_2Form_r<(outs GPR:$Rt), (ins GPR:$Ra), + "clz\t$Rt, $Ra", + [(set GPR:$Rt, (ctlz GPR:$Ra))], + 0b000111>; + + +//===----------------------------------------------------------------------===// // Load/Store Instructions // Index: test/CodeGen/NDS32/count-zero.ll =================================================================== --- /dev/null +++ test/CodeGen/NDS32/count-zero.ll @@ -0,0 +1,115 @@ +; RUN: llc < %s | FileCheck %s +target datalayout = "e-m:e-p:32:32-i64:64-a:0:32-n32-S64" +target triple = "nds32le---elf" + +%struct.anon = type { i32, i32 } + +@tab = local_unnamed_addr global [8 x %struct.anon] [%struct.anon { i32 -2147483648, i32 32 }, %struct.anon { i32 -1515870811, i32 1 }, %struct.anon { i32 1515870810, i32 2 }, %struct.anon { i32 -889323520, i32 18 }, %struct.anon { i32 32768, i32 16 }, %struct.anon { i32 42405, i32 1 }, %struct.anon { i32 23130, i32 2 }, %struct.anon { i32 3232, i32 6 }], align 4 + +; Function Attrs: noreturn nounwind +define i32 @count_zero() local_unnamed_addr #0 { +entry: + %0 = load i32, i32* getelementptr inbounds ([8 x %struct.anon], [8 x %struct.anon]* @tab, i32 0, i32 0, i32 0), align 4 + %1 = tail call i32 @llvm.cttz.i32(i32 %0, i1 true) +; CHECK: clz $r1, $r1 + %2 = add nuw nsw i32 %1, 1 + %iszero = icmp eq i32 %0, 0 + %ffs = select i1 %iszero, i32 0, i32 %2 + %3 = load i32, i32* getelementptr inbounds ([8 x %struct.anon], [8 x %struct.anon]* @tab, i32 0, i32 0, i32 1), align 4 + %cmp2 = icmp eq i32 %ffs, %3 + br i1 %cmp2, label %for.cond, label %if.then + +for.cond: ; preds = %entry + %4 = load i32, i32* getelementptr inbounds ([8 x %struct.anon], [8 x %struct.anon]* @tab, i32 0, i32 1, i32 0), align 4 + %5 = tail call i32 @llvm.cttz.i32(i32 %4, i1 true) +; CHECK: clz $r3, $r3 + %6 = add nuw nsw i32 %5, 1 + %iszero.1 = icmp eq i32 %4, 0 + %ffs.1 = select i1 %iszero.1, i32 0, i32 %6 + %7 = load i32, i32* getelementptr inbounds ([8 x %struct.anon], [8 x %struct.anon]* @tab, i32 0, i32 1, i32 1), align 4 + %cmp2.1 = icmp eq i32 %ffs.1, %7 + br i1 %cmp2.1, label %for.cond.1, label %if.then + +if.then: ; preds = %for.cond.6, %for.cond.5, %for.cond.4, %for.cond.3, %for.cond.2, %for.cond.1, %for.cond, %entry + tail call void @abort() #3 + unreachable + +for.cond.1: ; preds = %for.cond + %8 = load i32, i32* getelementptr inbounds ([8 x %struct.anon], [8 x %struct.anon]* @tab, i32 0, i32 2, i32 0), align 4 + %9 = tail call i32 @llvm.cttz.i32(i32 %8, i1 true) +; CHECK: clz $r1, $r1 + %10 = add nuw nsw i32 %9, 1 + %iszero.2 = icmp eq i32 %8, 0 + %ffs.2 = select i1 %iszero.2, i32 0, i32 %10 + %11 = load i32, i32* getelementptr inbounds ([8 x %struct.anon], [8 x %struct.anon]* @tab, i32 0, i32 2, i32 1), align 4 + %cmp2.2 = icmp eq i32 %ffs.2, %11 + br i1 %cmp2.2, label %for.cond.2, label %if.then + +for.cond.2: ; preds = %for.cond.1 + %12 = load i32, i32* getelementptr inbounds ([8 x %struct.anon], [8 x %struct.anon]* @tab, i32 0, i32 3, i32 0), align 4 + %13 = tail call i32 @llvm.cttz.i32(i32 %12, i1 true) +; CHECK: clz $r3, $r3 + %14 = add nuw nsw i32 %13, 1 + %iszero.3 = icmp eq i32 %12, 0 + %ffs.3 = select i1 %iszero.3, i32 0, i32 %14 + %15 = load i32, i32* getelementptr inbounds ([8 x %struct.anon], [8 x %struct.anon]* @tab, i32 0, i32 3, i32 1), align 4 + %cmp2.3 = icmp eq i32 %ffs.3, %15 + br i1 %cmp2.3, label %for.cond.3, label %if.then + +for.cond.3: ; preds = %for.cond.2 + %16 = load i32, i32* getelementptr inbounds ([8 x %struct.anon], [8 x %struct.anon]* @tab, i32 0, i32 4, i32 0), align 4 + %17 = tail call i32 @llvm.cttz.i32(i32 %16, i1 true) +; CHECK: clz $r1, $r1 + %18 = add nuw nsw i32 %17, 1 + %iszero.4 = icmp eq i32 %16, 0 + %ffs.4 = select i1 %iszero.4, i32 0, i32 %18 + %19 = load i32, i32* getelementptr inbounds ([8 x %struct.anon], [8 x %struct.anon]* @tab, i32 0, i32 4, i32 1), align 4 + %cmp2.4 = icmp eq i32 %ffs.4, %19 + br i1 %cmp2.4, label %for.cond.4, label %if.then + +for.cond.4: ; preds = %for.cond.3 + %20 = load i32, i32* getelementptr inbounds ([8 x %struct.anon], [8 x %struct.anon]* @tab, i32 0, i32 5, i32 0), align 4 + %21 = tail call i32 @llvm.cttz.i32(i32 %20, i1 true) +; CHECK: clz $r3, $r3 + %22 = add nuw nsw i32 %21, 1 + %iszero.5 = icmp eq i32 %20, 0 + %ffs.5 = select i1 %iszero.5, i32 0, i32 %22 + %23 = load i32, i32* getelementptr inbounds ([8 x %struct.anon], [8 x %struct.anon]* @tab, i32 0, i32 5, i32 1), align 4 + %cmp2.5 = icmp eq i32 %ffs.5, %23 + br i1 %cmp2.5, label %for.cond.5, label %if.then + +for.cond.5: ; preds = %for.cond.4 + %24 = load i32, i32* getelementptr inbounds ([8 x %struct.anon], [8 x %struct.anon]* @tab, i32 0, i32 6, i32 0), align 4 + %25 = tail call i32 @llvm.cttz.i32(i32 %24, i1 true) +; CHECK: clz $r1, $r1 + %26 = add nuw nsw i32 %25, 1 + %iszero.6 = icmp eq i32 %24, 0 + %ffs.6 = select i1 %iszero.6, i32 0, i32 %26 + %27 = load i32, i32* getelementptr inbounds ([8 x %struct.anon], [8 x %struct.anon]* @tab, i32 0, i32 6, i32 1), align 4 + %cmp2.6 = icmp eq i32 %ffs.6, %27 + br i1 %cmp2.6, label %for.cond.6, label %if.then + +for.cond.6: ; preds = %for.cond.5 + %28 = load i32, i32* getelementptr inbounds ([8 x %struct.anon], [8 x %struct.anon]* @tab, i32 0, i32 7, i32 0), align 4 + %29 = tail call i32 @llvm.cttz.i32(i32 %28, i1 true) +; CHECK: clz $r3, $r3 + %30 = add nuw nsw i32 %29, 1 + %iszero.7 = icmp eq i32 %28, 0 + %ffs.7 = select i1 %iszero.7, i32 0, i32 %30 + %31 = load i32, i32* getelementptr inbounds ([8 x %struct.anon], [8 x %struct.anon]* @tab, i32 0, i32 7, i32 1), align 4 + %cmp2.7 = icmp eq i32 %ffs.7, %31 + br i1 %cmp2.7, label %for.cond.7, label %if.then + +for.cond.7: ; preds = %for.cond.6 + tail call void @exit(i32 0) #3 + unreachable +} + +; Function Attrs: nounwind readnone +declare i32 @llvm.cttz.i32(i32, i1) #1 + +; Function Attrs: noreturn +declare void @abort() local_unnamed_addr #2 + +; Function Attrs: noreturn +declare void @exit(i32) local_unnamed_addr #2