Index: lib/Target/NDS32/NDS32InstrInfo.td =================================================================== --- lib/Target/NDS32/NDS32InstrInfo.td +++ lib/Target/NDS32/NDS32InstrInfo.td @@ -614,6 +614,10 @@ def : Pat<(setule GPR:$lhs, GPR:$rhs), (XORI (SLT GPR:$rhs, GPR:$lhs), 1)>; +// load patterns +def : Pat<(i32 (extloadi16 addr_imm15s_half:$src)), (LHI addr_imm15s_half:$src)>; +def : Pat<(i32 (extloadi8 addr_imm15s_byte:$src)), (LBI addr_imm15s_byte:$src)>; + //===----------------------------------------------------------------------===// // Conditional Move Instructions Index: test/CodeGen/NDS32/anyext.ll =================================================================== --- /dev/null +++ test/CodeGen/NDS32/anyext.ll @@ -0,0 +1,126 @@ +; RUN: llc < %s | FileCheck %s +target datalayout = "e-m:e-p:32:32-i64:64-a:0:32-n32-S64" +target triple = "nds32le---elf" + +@buf = global [5 x i16] [i16 1, i16 4, i16 16, i16 64, i16 256], align 2 +@buf1 = global [5 x i8] c"\01\04\10\06\05", align 1 + +; Function Attrs: noreturn nounwind +define i32 @main() local_unnamed_addr #0 { +bug.exit: + %0 = load i16, i16* getelementptr inbounds ([5 x i16], [5 x i16]* @buf, i32 0, i32 0), align 2 + %1 = sub i16 512, %0 + %conv1.i = zext i16 %1 to i32 +; CHECK: lhi $r1, [$r0 + (0)] + %2 = load i16, i16* getelementptr inbounds ([5 x i16], [5 x i16]* @buf, i32 0, i32 1), align 2 + %conv.i.1 = zext i16 %2 to i32 +; CHECK: lhi $r2, [$r0 + (2)] + %sub.i.1 = sub nsw i32 %conv1.i, %conv.i.1 + %3 = load i16, i16* getelementptr inbounds ([5 x i16], [5 x i16]* @buf, i32 0, i32 2), align 2 + %conv.i.2 = zext i16 %3 to i32 +; CHECK: lhi $r0, [$r0 + (4)] + %sub.i.2 = sub nsw i32 %sub.i.1, %conv.i.2 + %conv1.i.2 = and i32 %sub.i.2, 65535 + %phitmp = icmp eq i32 %conv1.i.2, 491 + br i1 %phitmp, label %if.end, label %if.then + +if.then: ; preds = %bug.exit + tail call void @abort() #3 + unreachable + +if.end: ; preds = %bug.exit + tail call void @exit(i32 0) #3 + unreachable +} + +; Function Attrs: norecurse nounwind readonly +define i32 @bug(i16 zeroext %value, i16* readonly %buffer, i16* readnone %bufend) local_unnamed_addr #1 { +entry: + %cmp8 = icmp ult i16* %buffer, %bufend + %conv19 = zext i16 %value to i32 + br i1 %cmp8, label %for.body.preheader, label %for.end + +for.body.preheader: ; preds = %entry + br label %for.body + +for.body: ; preds = %for.body.preheader, %for.body + %conv111 = phi i32 [ %conv1, %for.body ], [ %conv19, %for.body.preheader ] + %tmp.010 = phi i16* [ %incdec.ptr, %for.body ], [ %buffer, %for.body.preheader ] + %0 = load i16, i16* %tmp.010, align 2 + %conv = zext i16 %0 to i32 + %sub = sub nsw i32 %conv111, %conv + %incdec.ptr = getelementptr inbounds i16, i16* %tmp.010, i32 1 + %cmp = icmp ult i16* %incdec.ptr, %bufend + %conv1 = and i32 %sub, 65535 + br i1 %cmp, label %for.body, label %for.end.loopexit + +for.end.loopexit: ; preds = %for.body + br label %for.end + +for.end: ; preds = %for.end.loopexit, %entry + %conv1.lcssa = phi i32 [ %conv19, %entry ], [ %conv1, %for.end.loopexit ] + ret i32 %conv1.lcssa +} + +; Function Attrs: noreturn +declare void @abort() local_unnamed_addr #2 + +; Function Attrs: noreturn +declare void @exit(i32) local_unnamed_addr #2 + +; Function Attrs: noreturn nounwind +define i32 @main1() local_unnamed_addr #0 { +entry: + %0 = load i8, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @buf1, i32 0, i32 0), align 1 + %1 = sub i8 5, %0 + %conv1.i = zext i8 %1 to i32 +; CHECK: lbi $r1, [$r0 + (0)] + %2 = load i8, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @buf1, i32 0, i32 1), align 1 + %conv.i.1 = zext i8 %2 to i32 +; CHECK: lbi $r2, [$r0 + (1)] + %sub.i.1 = sub nsw i32 %conv1.i, %conv.i.1 + %3 = load i8, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @buf1, i32 0, i32 2), align 1 + %conv.i.2 = zext i8 %3 to i32 +; CHECK: lbi $r0, [$r0 + (2)] + %sub.i.2 = sub nsw i32 %sub.i.1, %conv.i.2 + %conv1.i.2 = and i32 %sub.i.2, 255 + %cmp = icmp eq i32 %conv1.i.2, 9 + br i1 %cmp, label %if.end, label %if.then + +if.then: ; preds = %entry + tail call void @abort() #3 + unreachable + +if.end: ; preds = %entry + tail call void @exit(i32 0) #3 + unreachable +} + +; Function Attrs: norecurse nounwind readonly +define i32 @bug1(i8 zeroext %value, i8* readonly %buffer, i8* readnone %bufend) local_unnamed_addr #1 { +entry: + %cmp8 = icmp ult i8* %buffer, %bufend + %conv19 = zext i8 %value to i32 + br i1 %cmp8, label %for.body.preheader, label %for.end + +for.body.preheader: ; preds = %entry + br label %for.body + +for.body: ; preds = %for.body.preheader, %for.body + %conv111 = phi i32 [ %conv1, %for.body ], [ %conv19, %for.body.preheader ] + %tmp.010 = phi i8* [ %incdec.ptr, %for.body ], [ %buffer, %for.body.preheader ] + %0 = load i8, i8* %tmp.010, align 1 + %conv = zext i8 %0 to i32 + %sub = sub nsw i32 %conv111, %conv + %incdec.ptr = getelementptr inbounds i8, i8* %tmp.010, i32 1 + %conv1 = and i32 %sub, 255 + %exitcond = icmp eq i8* %incdec.ptr, %bufend + br i1 %exitcond, label %for.end.loopexit, label %for.body + +for.end.loopexit: ; preds = %for.body + br label %for.end + +for.end: ; preds = %for.end.loopexit, %entry + %conv1.lcssa = phi i32 [ %conv19, %entry ], [ %conv1, %for.end.loopexit ] + ret i32 %conv1.lcssa +}