Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@ -0,0 +1,44 @@
; RUN: llc -march=lanai < %s | FileCheck %s
; RUN: llc -march=lanai < %s -code-model=small | FileCheck -check-prefix CHECK-SMALL %s
@data = external global [0 x i32] ; <[0 x i32]*> [#uses=5]
define i32 @foo() nounwind readonly {
entry:
; CHECK-SMALL-LABEL: foo:
; CHECK-SMALL: ld [data], %rv
; CHECK-LABEL: foo:
; CHECK: mov hi(data), %r[[REGISTER:[0-9]+]]
; CHECK: or %r[[REGISTER]], lo(data), %r[[REGISTER]]
; CHECK: ld 0[%r[[REGISTER]]], %rv
%0 = load i32, i32* getelementptr ([0 x i32], [0 x i32]* @data, i64 0, i64 0), align 4 ; <i32> [#uses=1]
ret i32 %0
}
define i32 @foo1() nounwind readonly {
entry:
; CHECK-SMALL-LABEL: foo1:
; CHECK-SMALL: mov data, %r[[REGISTER:[0-9]+]]
; CHECK-SMALL: ld 40[%r[[REGISTER]]], %rv
; CHECK-LABEL: foo1:
; CHECK: mov hi(data), %r[[REGISTER:[0-9]+]]
; CHECK: or %r[[REGISTER]], lo(data), %r[[REGISTER]]
; CHECK: ld 40[%r[[REGISTER]]], %rv
%0 = load i32, i32* getelementptr ([0 x i32], [0 x i32]* @data, i32 0, i64 10), align 4 ; <i32> [#uses=1]
ret i32 %0
}
@y = local_unnamed_addr global i32* null, section ".ldata,block", align 8
define i32 @foo2() nounwind readonly {
entry:
; CHECK-SMALL-LABEL: foo2:
; CHECK-SMALL: mov hi(y), %r[[REGISTER:[0-9]+]]
; CHECK-SMALL: or %r[[REGISTER]], lo(y), %r[[REGISTER]]
; CHECK-LABEL: foo2:
; CHECK: mov hi(y), %r[[REGISTER:[0-9]+]]
; CHECK: or %r[[REGISTER]], lo(y), %r[[REGISTER]]
%0 = load i32*, i32** @y, align 8
%1 = load i32, i32* %0, align 4
ret i32 %1
}

View File

@ -0,0 +1,96 @@
; RUN: llc < %s | FileCheck %s
; Test that basic 32-bit integer comparison operations assemble as expected.
target datalayout = "E-m:e-p:32:32-i64:64-a:0:32-n32-S64"
target triple = "lanai"
; CHECK-LABEL: eq_i32:
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
; CHECK-NEXT: seq
define i32 @eq_i32(i32 %x, i32 %y) {
%a = icmp eq i32 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: ne_i32:
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
; CHECK-NEXT: sne
define i32 @ne_i32(i32 %x, i32 %y) {
%a = icmp ne i32 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: slt_i32:
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
; CHECK-NEXT: slt
define i32 @slt_i32(i32 %x, i32 %y) {
%a = icmp slt i32 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: sle_i32:
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
; CHECK-NEXT: sle
define i32 @sle_i32(i32 %x, i32 %y) {
%a = icmp sle i32 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: ult_i32:
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
; CHECK-NEXT: sult
define i32 @ult_i32(i32 %x, i32 %y) {
%a = icmp ult i32 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: ule_i32:
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
; CHECK-NEXT: sule
define i32 @ule_i32(i32 %x, i32 %y) {
%a = icmp ule i32 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: sgt_i32:
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
; CHECK-NEXT: sgt
define i32 @sgt_i32(i32 %x, i32 %y) {
%a = icmp sgt i32 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: sge_i32:
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
; CHECK-NEXT: sge
define i32 @sge_i32(i32 %x, i32 %y) {
%a = icmp sge i32 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: ugt_i32:
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
; CHECK-NEXT: sugt
define i32 @ugt_i32(i32 %x, i32 %y) {
%a = icmp ugt i32 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: uge_i32:
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
; CHECK-NEXT: suge
define i32 @uge_i32(i32 %x, i32 %y) {
%a = icmp uge i32 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

View File

@ -0,0 +1,108 @@
; RUN: llc < %s | FileCheck %s
; Test that basic 64-bit integer comparison operations assemble as expected.
target datalayout = "E-m:e-p:32:32-i64:64-a:0:32-n32-S64"
target triple = "lanai"
; CHECK-LABEL: eq_i64:
; CHECK: xor
; CHECK: xor
; CHECK: or.f
; CHECK-NEXT: seq
define i32 @eq_i64(i64 inreg %x, i64 inreg %y) {
%a = icmp eq i64 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: ne_i64:
; CHECK: xor
; CHECK: xor
; CHECK: or.f
; CHECK-NEXT: sne
define i32 @ne_i64(i64 inreg %x, i64 inreg %y) {
%a = icmp ne i64 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: slt_i64:
; CHECK: sub.f %r7, %r19, %r3
; CHECK: subb.f %r6, %r18, %r3
; CHECK-NEXT: slt
define i32 @slt_i64(i64 inreg %x, i64 inreg %y) {
%a = icmp slt i64 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: sle_i64:
; CHECK: sub.f %r19, %r7, %r3
; CHECK: subb.f %r18, %r6, %r3
; CHECK-NEXT: sge %rv
define i32 @sle_i64(i64 inreg %x, i64 inreg %y) {
%a = icmp sle i64 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: ult_i64:
; CHECK: sub.f %r7, %r19, %r3
; CHECK: subb.f %r6, %r18, %r3
; CHECK-NEXT: sult %rv
define i32 @ult_i64(i64 inreg %x, i64 inreg %y) {
%a = icmp ult i64 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: ule_i64:
; CHECK: sub.f %r19, %r7, %r3
; CHECK: subb.f %r18, %r6, %r3
; CHECK-NEXT: suge %rv
define i32 @ule_i64(i64 inreg %x, i64 inreg %y) {
%a = icmp ule i64 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: sgt_i64:
; CHECK: sub.f %r19, %r7, %r3
; CHECK: subb.f %r18, %r6, %r3
; CHECK-NEXT: slt %rv
define i32 @sgt_i64(i64 inreg %x, i64 inreg %y) {
%a = icmp sgt i64 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: sge_i64:
; CHECK: sub.f %r7, %r19, %r3
; CHECK: subb.f %r6, %r18, %r3
; CHECK-NEXT: sge %rv
define i32 @sge_i64(i64 inreg %x, i64 inreg %y) {
%a = icmp sge i64 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: ugt_i64:
; CHECK: sub.f %r19, %r7, %r3
; CHECK: subb.f %r18, %r6, %r3
; CHECK-NEXT: sult %rv
define i32 @ugt_i64(i64 inreg %x, i64 inreg %y) {
%a = icmp ugt i64 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}
; CHECK-LABEL: uge_i64:
; CHECK: sub.f %r7, %r19, %r3
; CHECK: subb.f %r6, %r18, %r3
; CHECK-NEXT: suge %rv
define i32 @uge_i64(i64 inreg %x, i64 inreg %y) {
%a = icmp uge i64 %x, %y
%b = zext i1 %a to i32
ret i32 %b
}

View File

@ -0,0 +1,107 @@
; RUN: llc < %s | FileCheck %s
; Test custom lowering for 32-bit integer multiplication.
target datalayout = "E-m:e-p:32:32-i64:64-a:0:32-n32-S64"
target triple = "lanai"
; CHECK-LABEL: f6:
; CHECK: sh %r6, 0x1, %r{{[0-9]+}}
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @f6(i32 inreg %a) #0 {
%1 = mul nsw i32 %a, 6
ret i32 %1
}
; CHECK-LABEL: f7:
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
; CHECK: sub %r{{[0-9]+}}, %r6, %rv
define i32 @f7(i32 inreg %a) #0 {
%1 = mul nsw i32 %a, 7
ret i32 %1
}
; CHECK-LABEL: f8:
; CHECK: sh %r6, 0x3, %rv
define i32 @f8(i32 inreg %a) #0 {
%1 = shl nsw i32 %a, 3
ret i32 %1
}
; CHECK-LABEL: f9:
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
; CHECK: add %r{{[0-9]+}}, %r6, %rv
define i32 @f9(i32 inreg %a) #0 {
%1 = mul nsw i32 %a, 9
ret i32 %1
}
; CHECK-LABEL: f10:
; CHECK: sh %r6, 0x1, %r{{[0-9]+}}
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
; CHECK: add %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @f10(i32 inreg %a) #0 {
%1 = mul nsw i32 %a, 10
ret i32 %1
}
; CHECK-LABEL: f1280:
; CHECK: sh %r6, 0x8, %r{{[0-9]+}}
; CHECK: sh %r6, 0xa, %r{{[0-9]+}}
; CHECK: add %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @f1280(i32 inreg %a) #0 {
%1 = mul nsw i32 %a, 1280
ret i32 %1
}
; CHECK-LABEL: fm6:
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
; CHECK: sh %r6, 0x1, %r{{[0-9]+}}
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @fm6(i32 inreg %a) #0 {
%1 = mul nsw i32 %a, -6
ret i32 %1
}
; CHECK-LABEL: fm7:
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
; CHECK: sub %r6, %r{{[0-9]+}}, %rv
define i32 @fm7(i32 inreg %a) #0 {
%1 = mul nsw i32 %a, -7
ret i32 %1
}
; CHECK-LABEL: fm8:
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @fm8(i32 inreg %a) #0 {
%1 = mul nsw i32 %a, -8
ret i32 %1
}
; CHECK-LABEL: fm9:
; CHECK: sub %r0, %r6, %r{{[0-9]+}}
; CHECK: sh %r6, 0x3, %r9
; CHECK: sub %r{{[0-9]+}}, %r9, %rv
define i32 @fm9(i32 inreg %a) #0 {
%1 = mul nsw i32 %a, -9
ret i32 %1
}
; CHECK-LABEL: fm10:
; CHECK: sh %r6, 0x1, %r{{[0-9]+}}
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @fm10(i32 inreg %a) #0 {
%1 = mul nsw i32 %a, -10
ret i32 %1
}
; CHECK-LABEL: h1:
; CHECK: __mulsi3
define i32 @h1(i32 inreg %a) #0 {
%1 = mul i32 %a, -1431655765
ret i32 %1
}

View File

@ -0,0 +1,41 @@
; RUN: llc -march=lanai < %s | FileCheck %s
; RUN: llc -march=lanai --lanai-nop-delay-filler < %s | \
; RUN: FileCheck %s --check-prefix=NOP
; CHECK: bt f
; CHECK-NEXT: or
; NOP: bt f
; NOP-NEXT: nop
; ModuleID = 'delay_filler.c'
target datalayout = "E-m:e-p:32:32-i64:64-a:0:32-n32-S64"
target triple = "lanai"
; Function Attrs: nounwind
define i32 @g(i32 inreg %n) #0 {
entry:
%cmp5 = icmp sgt i32 %n, 0
br i1 %cmp5, label %for.body.preheader, label %for.cond.cleanup
for.body.preheader: ; preds = %entry
br label %for.body
for.cond.cleanup.loopexit: ; preds = %for.body
%call.lcssa = phi i32 [ %call, %for.body ]
br label %for.cond.cleanup
for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry
%a.0.lcssa = phi i32 [ undef, %entry ], [ %call.lcssa, %for.cond.cleanup.loopexit ]
ret i32 %a.0.lcssa
for.body: ; preds = %for.body.preheader, %for.body
%i.07 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]
%a.06 = phi i32 [ %call, %for.body ], [ undef, %for.body.preheader ]
%call = tail call i32 @f(i32 inreg %a.06) #2
%inc = add nuw nsw i32 %i.07, 1
%exitcond = icmp eq i32 %inc, %n
br i1 %exitcond, label %for.cond.cleanup.loopexit, label %for.body
}
declare i32 @f(i32 inreg) #1

View File

@ -0,0 +1,145 @@
; RUN: llc < %s -asm-verbose=false | FileCheck %s
; Test that basic 32-bit integer operations assemble as expected.
target datalayout = "E-m:e-p:32:32-i64:64-a:0:32-n32-S64"
target triple = "lanai"
; Function Attrs: nounwind readnone
declare i32 @llvm.ctpop.i32(i32) #1
; Function Attrs: nounwind readnone
declare i32 @llvm.ctlz.i32(i32, i1) #1
; Function Attrs: nounwind readnone
declare i32 @llvm.cttz.i32(i32, i1) #1
; CHECK-LABEL: add32:
; CHECK: add %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @add32(i32 %x, i32 %y) {
%a = add i32 %x, %y
ret i32 %a
}
; CHECK-LABEL: sub32:
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @sub32(i32 %x, i32 %y) {
%a = sub i32 %x, %y
ret i32 %a
}
; CHECK-LABEL: mul32:
; CHECK: bt __mulsi3
define i32 @mul32(i32 %x, i32 %y) {
%a = mul i32 %x, %y
ret i32 %a
}
; CHECK-LABEL: sdiv32:
; CHECK: bt __divsi3
define i32 @sdiv32(i32 %x, i32 %y) {
%a = sdiv i32 %x, %y
ret i32 %a
}
; CHECK-LABEL: udiv32:
; CHECK: bt __udivsi3
define i32 @udiv32(i32 %x, i32 %y) {
%a = udiv i32 %x, %y
ret i32 %a
}
; CHECK-LABEL: srem32:
; CHECK: bt __modsi3
define i32 @srem32(i32 %x, i32 %y) {
%a = srem i32 %x, %y
ret i32 %a
}
; CHECK-LABEL: urem32:
; CHECK: bt __umodsi3
define i32 @urem32(i32 %x, i32 %y) {
%a = urem i32 %x, %y
ret i32 %a
}
; CHECK-LABEL: and32:
; CHECK: and %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @and32(i32 %x, i32 %y) {
%a = and i32 %x, %y
ret i32 %a
}
; CHECK-LABEL: or32:
; CHECK: or %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @or32(i32 %x, i32 %y) {
%a = or i32 %x, %y
ret i32 %a
}
; CHECK-LABEL: xor32:
; CHECK: xor %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @xor32(i32 %x, i32 %y) {
%a = xor i32 %x, %y
ret i32 %a
}
; CHECK-LABEL: shl32:
; CHECK: sh %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @shl32(i32 %x, i32 %y) {
%a = shl i32 %x, %y
ret i32 %a
}
; CHECK-LABEL: shr32:
; CHECK: sub %r0, %r{{[0-9]+}}, %r{{[0-9]+}}
; CHECK: sh %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @shr32(i32 %x, i32 %y) {
%a = lshr i32 %x, %y
ret i32 %a
}
; CHECK-LABEL: sar32
; CHECK: sub %r0, %r{{[0-9]+}}, %r{{[0-9]+}}
; CHECK: sha %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @sar32(i32 %x, i32 %y) {
%a = ashr i32 %x, %y
ret i32 %a
}
; CHECK-LABEL: clz32:
; CHECK: leadz %r{{[0-9]+}}, %rv
define i32 @clz32(i32 %x) {
%a = call i32 @llvm.ctlz.i32(i32 %x, i1 false)
ret i32 %a
}
; CHECK-LABEL: clz32_zero_undef:
; CHECK-NOT: sub.f
; CHECK: leadz %r{{[0-9]+}}, %rv
define i32 @clz32_zero_undef(i32 %x) {
%a = call i32 @llvm.ctlz.i32(i32 %x, i1 true)
ret i32 %a
}
; CHECK-LABEL: ctz32:
; CHECK: trailz %r{{[0-9]+}}, %rv
define i32 @ctz32(i32 %x) {
%a = call i32 @llvm.cttz.i32(i32 %x, i1 false)
ret i32 %a
}
; CHECK-LABEL: ctz32_zero_undef:
; CHECK-NOT: sub.f
; CHECK: trailz %r{{[0-9]+}}, %rv
define i32 @ctz32_zero_undef(i32 %x) {
%a = call i32 @llvm.cttz.i32(i32 %x, i1 true)
ret i32 %a
}
; CHECK-LABEL: popcnt32:
; CHECK: popc %r{{[0-9]+}}, %rv
define i32 @popcnt32(i32 %x) {
%a = call i32 @llvm.ctpop.i32(i32 %x)
ret i32 %a
}

View File

@ -0,0 +1,56 @@
; REQUIRES: asserts
; RUN: llc %s -mtriple=lanai-unknown-unknown -debug-only=machine-scheduler -o /dev/null 2>&1 | FileCheck %s
; Make sure there are no control dependencies between memory operations that
; are trivially disjoint.
; Function Attrs: norecurse nounwind uwtable
define i32 @foo(i8* inreg nocapture %x) {
entry:
%0 = bitcast i8* %x to i32*
store i32 1, i32* %0, align 4
%arrayidx1 = getelementptr inbounds i8, i8* %x, i32 4
%1 = bitcast i8* %arrayidx1 to i32*
store i32 2, i32* %1, align 4
%arrayidx2 = getelementptr inbounds i8, i8* %x, i32 12
%2 = bitcast i8* %arrayidx2 to i32*
%3 = load i32, i32* %2, align 4
%arrayidx3 = getelementptr inbounds i8, i8* %x, i32 10
%4 = bitcast i8* %arrayidx3 to i16*
store i16 3, i16* %4, align 2
%5 = bitcast i8* %arrayidx2 to i16*
store i16 4, i16* %5, align 2
%arrayidx5 = getelementptr inbounds i8, i8* %x, i32 14
store i8 5, i8* %arrayidx5, align 1
%arrayidx6 = getelementptr inbounds i8, i8* %x, i32 15
store i8 6, i8* %arrayidx6, align 1
%arrayidx7 = getelementptr inbounds i8, i8* %x, i32 16
store i8 7, i8* %arrayidx7, align 1
ret i32 %3
}
; CHECK-LABEL: foo
; CHECK-LABEL: SU({{.*}}): SW_RI{{.*}}, 0,
; CHECK: # preds left : 2
; CHECK: # succs left : 0
; CHECK-LABEL: SU({{.*}}): SW_RI{{.*}}, 4,
; CHECK: # preds left : 2
; CHECK: # succs left : 0
; CHECK-LABEL: SU({{.*}}): %{{.*}} = LDW_RI{{.*}}, 12,
; CHECK: # preds left : 1
; CHECK: # succs left : 4
; CHECK-LABEL: SU({{.*}}): STH_RI{{.*}}, 10,
; CHECK: # preds left : 2
; CHECK: # succs left : 0
; CHECK-LABEL: SU({{.*}}): STH_RI{{.*}}, 12,
; CHECK: # preds left : 3
; CHECK: # succs left : 0
; CHECK-LABEL: SU({{.*}}): STB_RI{{.*}}, 14,
; CHECK: # preds left : 3
; CHECK: # succs left : 0
; CHECK-LABEL: SU({{.*}}): STB_RI{{.*}}, 15,
; CHECK: # preds left : 3
; CHECK: # succs left : 0
; CHECK-LABEL: SU({{.*}}): STB_RI{{.*}}, 16,
; CHECK: # preds left : 2
; CHECK: # succs left : 0

View File

@ -0,0 +1,3 @@
if not 'Lanai' in config.root.targets:
config.unsupported = True

View File

@ -0,0 +1,24 @@
; RUN: llc < %s -mtriple=lanai-unknown-unknown | FileCheck %s
; Test left-shift i64 lowering does not result in call being inserted.
; CHECK-LABEL: shift
; CHECKT: bt __ashldi3
; CHECK: or %r0, 0x0, %r[[T0:[0-9]+]]
; CHECK: mov 0x20, %r[[T1:[0-9]+]]
; CHECK: sub %r[[T1]], %r[[ShAmt:[0-9]+]], %r[[T1]]
; CHECK: sub %r0, %r[[T1]], %r[[T1]]
; CHECK: sh %r[[ShOpB:[0-9]+]], %r[[T1]], %r[[T1]]
; CHECK: sub.f %r[[ShAmt]], 0x0, %r0
; CHECK: sel.eq %r0, %r[[T1]], %r[[T1]]
; CHECK: sh %r[[ShOpA:[0-9]+]], %r[[ShAmt]], %r[[T2:[0-9]+]]
; CHECK: or %r[[T1]], %r[[T2]], %rv
; CHECK: sub.f %r[[ShAmt]], 0x20, %r[[T1]]
; CHECK: sh.pl %r[[ShOpB]], %r[[T1]], %rv
; CHECK: sh.mi %r[[ShOpB]], %r[[ShAmt]], %r[[T0]]
define i64 @shift(i64 inreg, i32 inreg) {
%3 = zext i32 %1 to i64
%4 = shl i64 %0, %3
ret i64 %4
}

View File

@ -0,0 +1,48 @@
; RUN: llc < %s | FileCheck %s
; Test that unnecessary masking with 0x1 is not inserted.
target datalayout = "E-m:e-p:32:32-i64:64-a:0:32-n32-S64"
target triple = "lanai"
; CHECK-LABEL: masking:
; CHECK-NOT: mov 1
define i32 @masking(i32 inreg %a, i32 inreg %b, i32 inreg %c, i32 inreg %d) {
entry:
%cmp = icmp ne i32 %a, 0
%cmp1 = icmp ult i32 %a, %b
%or.cond = and i1 %cmp, %cmp1
br i1 %or.cond, label %return, label %if.end
if.end: ; preds = %entry
%cmp2 = icmp ne i32 %b, 0
%cmp4 = icmp ult i32 %b, %c
%or.cond29 = and i1 %cmp2, %cmp4
br i1 %or.cond29, label %return, label %if.end6
if.end6: ; preds = %if.end
%cmp7 = icmp ne i32 %c, 0
%cmp9 = icmp ult i32 %c, %d
%or.cond30 = and i1 %cmp7, %cmp9
br i1 %or.cond30, label %return, label %if.end11
if.end11: ; preds = %if.end6
%cmp12 = icmp ne i32 %d, 0
%cmp14 = icmp ult i32 %d, %a
%or.cond31 = and i1 %cmp12, %cmp14
%b. = select i1 %or.cond31, i32 %b, i32 21
ret i32 %b.
return: ; preds = %if.end6, %if.end, %entry
%retval.0 = phi i32 [ %c, %entry ], [ %d, %if.end ], [ %a, %if.end6 ]
ret i32 %retval.0
}
; CHECK-LABEL: notnot:
; CHECK-NOT: mov 1
define i32 @notnot(i32 %x) {
entry:
%tobool = icmp ne i32 %x, 0
%lnot.ext = zext i1 %tobool to i32
ret i32 %lnot.ext
}

View File

@ -0,0 +1,35 @@
; RUN: llc < %s -march=lanai | FileCheck %s
; RUN: llc < %s -march=lanai -disable-lanai-mem-alu-combiner | \
; RUN: FileCheck %s -check-prefix=CHECK-DIS
; CHECK-LABEL: sum,
; CHECK: ld [%r{{[0-9]+}}++], %r{{[0-9]+}}{{$}}
; CHECK-DIS-LABEL: sum,
; CHECK-DIS-NOT: ++],
define i32 @sum(i32* inreg nocapture readonly %data, i32 inreg %n) {
entry:
%cmp6 = icmp sgt i32 %n, 0
br i1 %cmp6, label %for.body.preheader, label %for.cond.cleanup
for.body.preheader: ; preds = %entry
br label %for.body
for.cond.cleanup.loopexit: ; preds = %for.body
%add.lcssa = phi i32 [ %add, %for.body ]
br label %for.cond.cleanup
for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry
%sum_.0.lcssa = phi i32 [ 0, %entry ], [ %add.lcssa, %for.cond.cleanup.loopexit ]
ret i32 %sum_.0.lcssa
for.body: ; preds = %for.body.preheader, %for.body
%i.08 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]
%sum_.07 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
%arrayidx = getelementptr inbounds i32, i32* %data, i32 %i.08
%0 = load i32, i32* %arrayidx, align 4
%add = add nsw i32 %0, %sum_.07
%inc = add nuw nsw i32 %i.08, 1
%exitcond = icmp eq i32 %inc, %n
br i1 %exitcond, label %for.cond.cleanup.loopexit, label %for.body
}

View File

@ -0,0 +1,60 @@
; RUN: llc -march=lanai < %s | FileCheck %s
; Test the in place lowering of mul i32.
define i32 @f6(i32 inreg %a) #0 {
entry:
%mul = mul nsw i32 %a, 6
ret i32 %mul
}
; CHECK: sh %r6, 0x1, %r{{[0-9]+}}
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @f7(i32 inreg %a) #0 {
entry:
%mul = mul nsw i32 %a, 7
ret i32 %mul
}
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
; CHECK: sub %r{{[0-9]+}}, %r6, %rv
define i32 @f8(i32 inreg %a) #0 {
entry:
%mul = shl nsw i32 %a, 3
ret i32 %mul
}
; CHECK: sh %r6, 0x3, %rv
define i32 @fm6(i32 inreg %a) #0 {
entry:
%mul = mul nsw i32 %a, -6
ret i32 %mul
}
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
; CHECK: sh %r6, 0x1, %r{{[0-9]+}}
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @fm7(i32 inreg %a) #0 {
entry:
%mul = mul nsw i32 %a, -7
ret i32 %mul
}
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
; CHECK: sub %r6, %r{{[0-9]+}}, %rv
define i32 @fm8(i32 inreg %a) #0 {
entry:
%mul = mul nsw i32 %a, -8
ret i32 %mul
}
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
define i32 @h1(i32 inreg %a) #0 {
entry:
%mul = mul i32 %a, -1431655765
ret i32 %mul
}
; CHECK: h1
; CHECK: mulsi3

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
; RUN: llc < %s -mtriple=lanai-unknown-unknown | FileCheck %s
; Test right-shift i64 lowering does not result in call being inserted.
; CHECK-LABEL: shift
; CHECK-NOT: bt __lshrdi3
; CHECK: %rv
define i64 @shift(i64 inreg, i32 inreg) {
%3 = zext i32 %1 to i64
%4 = lshr i64 %0, %3
ret i64 %4
}

View File

@ -0,0 +1,41 @@
; RUN: llc < %s | FileCheck %s
; Test that Lanai select instruction is selected from LLVM select instruction.
target datalayout = "E-m:e-p:32:32-i64:64-a:0:32-n32-S64"
target triple = "lanai"
; CHECK-LABEL: select_i32_bool:
; CHECK: sub.f %r6, 0x0, %r0
; CHECK: sel.ne %r7, %r18, %rv
define i32 @select_i32_bool(i1 zeroext inreg %a, i32 inreg %b, i32 inreg %c) {
%cond = select i1 %a, i32 %b, i32 %c
ret i32 %cond
}
; CHECK-LABEL: select_i32_eq:
; CHECK: sub.f %r6, 0x0, %r0
; CHECK: sel.eq %r7, %r18, %rv
define i32 @select_i32_eq(i32 inreg %a, i32 inreg %b, i32 inreg %c) {
%cmp = icmp eq i32 %a, 0
%cond = select i1 %cmp, i32 %b, i32 %c
ret i32 %cond
}
; CHECK-LABEL: select_i32_ne:
; CHECK: sub.f %r6, 0x0, %r0
; CHECK: sel.ne %r7, %r18, %rv
define i32 @select_i32_ne(i32 inreg %a, i32 inreg %b, i32 inreg %c) {
%cmp = icmp ne i32 %a, 0
%cond = select i1 %cmp, i32 %b, i32 %c
ret i32 %cond
}
; CHECK-LABEL: select_i32_lt:
; CHECK: sub.f %r6, %r7, %r0
; CHECK: sel.lt %r6, %r7, %rv
define i32 @select_i32_lt(i32 inreg %x, i32 inreg %y) #0 {
%1 = icmp slt i32 %x, %y
%2 = select i1 %1, i32 %x, i32 %y
ret i32 %2
}

View File

@ -0,0 +1,15 @@
; RUN: llc < %s | FileCheck %s
; Test matching of and_hi.
target datalayout = "E-m:e-p:32:32-i64:64-a:0:32-n32-S64"
target triple = "lanai"
@x = common global i32 0, align 4
; CHECK-LABEL: setandhi:
; CHECK: mov 0xfffffe4a, %r{{[0-9]+}}
define void @setandhi() #0 {
store volatile i32 -438, i32* @x, align 4
ret void
}

View File

@ -0,0 +1,28 @@
; RUN: llc < %s -march=lanai | FileCheck %s
; Test lowering of shifts.
define i32 @irs(i32 inreg %a) #0 {
entry:
%shr = ashr i32 %a, 13
ret i32 %shr
}
; CHECK-LABEL: irs
; CHECK: sha %r6, -0xd, %rv
define i32 @urs(i32 inreg %a) #0 {
entry:
%shr = lshr i32 %a, 13
ret i32 %shr
}
; CHECK-LABEL: urs
; CHECK: sh %r6, -0xd, %rv
define i32 @ls(i32 inreg %a) #0 {
entry:
%shl = shl i32 %a, 13
ret i32 %shl
}
; CHECK-LABEL: ls
; CHECK: sh %r6, 0xd, %rv

View File

@ -0,0 +1,14 @@
; RUN: llc -mtriple=lanai < %s -o - | FileCheck %s
define void @f1() {
%c = alloca i8, align 1
ret void
}
; CHECK-LABEL: f1:
; CHECK: sub %sp, 0x10
define i32 @f2() {
ret i32 1
}
; CHECK-LABEL: f2:
; CHECK: sub %sp, 0x8

View File

@ -0,0 +1,109 @@
; RUN: llc < %s -mtriple=lanai | FileCheck %s
define i32 @f(i32 inreg %a, i32 inreg %b) nounwind ssp {
entry:
; CHECK-LABEL: f:
; CHECK: sub.f %r6, %r7, [[IN:%.*]]
; CHECK: sel.gt [[IN]], %r0, %rv
%cmp = icmp sgt i32 %a, %b
%sub = sub nsw i32 %a, %b
%sub. = select i1 %cmp, i32 %sub, i32 0
ret i32 %sub.
}
define i32 @g(i32 inreg %a, i32 inreg %b) nounwind ssp {
entry:
; CHECK-LABEL: g:
; CHECK: sub.f %r7, %r6, [[IN:%.*]]
; CHECK: sel.lt [[IN]], %r0, %rv
%cmp = icmp slt i32 %a, %b
%sub = sub nsw i32 %b, %a
%sub. = select i1 %cmp, i32 %sub, i32 0
ret i32 %sub.
}
define i32 @h(i32 inreg %a, i32 inreg %b) nounwind ssp {
entry:
; CHECK-LABEL: h:
; CHECK: sub.f %r6, 0x3, [[IN:%.*]]
; CHECK: sel.gt [[IN]], %r7, %rv
%cmp = icmp sgt i32 %a, 3
%sub = sub nsw i32 %a, 3
%sub. = select i1 %cmp, i32 %sub, i32 %b
ret i32 %sub.
}
define i32 @i(i32 inreg %a, i32 inreg %b) nounwind readnone ssp {
entry:
; CHECK-LABEL: i:
; CHECK: sub.f %r7, %r6, [[IN:%.*]]
; CHECK: sel.ult [[IN]], %r0, %rv
%cmp = icmp ult i32 %a, %b
%sub = sub i32 %b, %a
%sub. = select i1 %cmp, i32 %sub, i32 0
ret i32 %sub.
}
; If SR is live-out, we can't remove cmp if there exists a swapped sub.
define i32 @j(i32 inreg %a, i32 inreg %b) nounwind {
entry:
; CHECK-LABEL: j:
; CHECK: sub.f %r7, %r6, %r0
; CHECK: sub %r6, %r7, %rv
%cmp = icmp eq i32 %b, %a
%sub = sub nsw i32 %a, %b
br i1 %cmp, label %if.then, label %if.else
if.then:
%cmp2 = icmp sgt i32 %b, %a
%sel = select i1 %cmp2, i32 %sub, i32 %a
ret i32 %sel
if.else:
ret i32 %sub
}
declare void @abort()
declare void @exit(i32)
@t = common global i32 0
; If the comparison uses the C bit (signed overflow/underflow), we can't
; omit the comparison.
define i32 @cmp_ult0(i32 inreg %a, i32 inreg %b, i32 inreg %x, i32 inreg %y) {
entry:
; CHECK-LABEL: cmp_ult0
; CHECK: sub {{.*}}, 0x11, [[IN:%.*]]
; CHECK: sub.f [[IN]], 0x0, %r0
%load = load i32, i32* @t, align 4
%sub = sub i32 %load, 17
%cmp = icmp ult i32 %sub, 0
br i1 %cmp, label %if.then, label %if.else
if.then:
call void @abort()
unreachable
if.else:
call void @exit(i32 0)
unreachable
}
; Same for the V bit.
; TODO: add test that exercises V bit individually (VC/VS).
define i32 @cmp_gt0(i32 inreg %a, i32 inreg %b, i32 inreg %x, i32 inreg %y) {
entry:
; CHECK-LABEL: cmp_gt0
; CHECK: sub {{.*}}, 0x11, [[IN:%.*]]
; CHECK: sub.f [[IN]], 0x1, %r0
%load = load i32, i32* @t, align 4
%sub = sub i32 %load, 17
%cmp = icmp sgt i32 %sub, 0
br i1 %cmp, label %if.then, label %if.else
if.then:
call void @abort()
unreachable
if.else:
call void @exit(i32 0)
unreachable
}

View File

@ -0,0 +1,29 @@
; RUN: llc < %s -mtriple=lanai-unknown-unknown | FileCheck %s
; Test scheduling of subwords.
%struct.X = type { i16, i16 }
define void @f(%struct.X* inreg nocapture %c) #0 {
entry:
%a = getelementptr inbounds %struct.X, %struct.X* %c, i32 0, i32 0
%0 = load i16, i16* %a, align 2
%inc = add i16 %0, 1
store i16 %inc, i16* %a, align 2
%b = getelementptr inbounds %struct.X, %struct.X* %c, i32 0, i32 1
%1 = load i16, i16* %b, align 2
%dec = add i16 %1, -1
store i16 %dec, i16* %b, align 2
ret void
}
; Verify that the two loads occur before the stores. Without memory
; disambiguation and subword schedule, the resultant code was a per subword
; load-modify-store sequence instead of the more optimal schedule where all
; loads occurred before modification and storage.
; CHECK: uld.h
; CHECK-NEXT: uld.h
; CHECK-NEXT: add
; CHECK-NEXT: st.h
; CHECK-NEXT: sub
; CHECK-NEXT: st.h