mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	This implements the review suggestion to simplify the AArch64 backend. If we later discover that we *really* need the extra complexity of the ConstantIslands pass for performance reasons it can be resurrected. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@175258 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			281 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			LLVM
		
	
	
	
	
	
			
		
		
	
	
			281 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			LLVM
		
	
	
	
	
	
| ; RUN: llc -mtriple=aarch64-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s
 | |
| 
 | |
| @lhs = global fp128 zeroinitializer
 | |
| @rhs = global fp128 zeroinitializer
 | |
| 
 | |
| define fp128 @test_add() {
 | |
| ; CHECK: test_add:
 | |
| 
 | |
|   %lhs = load fp128* @lhs
 | |
|   %rhs = load fp128* @rhs
 | |
| ; CHECK: ldr q0, [{{x[0-9]+}}, #:lo12:lhs]
 | |
| ; CHECK: ldr q1, [{{x[0-9]+}}, #:lo12:rhs]
 | |
| 
 | |
|   %val = fadd fp128 %lhs, %rhs
 | |
| ; CHECK: bl __addtf3
 | |
|   ret fp128 %val
 | |
| }
 | |
| 
 | |
| define fp128 @test_sub() {
 | |
| ; CHECK: test_sub:
 | |
| 
 | |
|   %lhs = load fp128* @lhs
 | |
|   %rhs = load fp128* @rhs
 | |
| ; CHECK: ldr q0, [{{x[0-9]+}}, #:lo12:lhs]
 | |
| ; CHECK: ldr q1, [{{x[0-9]+}}, #:lo12:rhs]
 | |
| 
 | |
|   %val = fsub fp128 %lhs, %rhs
 | |
| ; CHECK: bl __subtf3
 | |
|   ret fp128 %val
 | |
| }
 | |
| 
 | |
| define fp128 @test_mul() {
 | |
| ; CHECK: test_mul:
 | |
| 
 | |
|   %lhs = load fp128* @lhs
 | |
|   %rhs = load fp128* @rhs
 | |
| ; CHECK: ldr q0, [{{x[0-9]+}}, #:lo12:lhs]
 | |
| ; CHECK: ldr q1, [{{x[0-9]+}}, #:lo12:rhs]
 | |
| 
 | |
|   %val = fmul fp128 %lhs, %rhs
 | |
| ; CHECK: bl __multf3
 | |
|   ret fp128 %val
 | |
| }
 | |
| 
 | |
| define fp128 @test_div() {
 | |
| ; CHECK: test_div:
 | |
| 
 | |
|   %lhs = load fp128* @lhs
 | |
|   %rhs = load fp128* @rhs
 | |
| ; CHECK: ldr q0, [{{x[0-9]+}}, #:lo12:lhs]
 | |
| ; CHECK: ldr q1, [{{x[0-9]+}}, #:lo12:rhs]
 | |
| 
 | |
|   %val = fdiv fp128 %lhs, %rhs
 | |
| ; CHECK: bl __divtf3
 | |
|   ret fp128 %val
 | |
| }
 | |
| 
 | |
| @var32 = global i32 0
 | |
| @var64 = global i64 0
 | |
| 
 | |
| define void @test_fptosi() {
 | |
| ; CHECK: test_fptosi:
 | |
|   %val = load fp128* @lhs
 | |
| 
 | |
|   %val32 = fptosi fp128 %val to i32
 | |
|   store i32 %val32, i32* @var32
 | |
| ; CHECK: bl __fixtfsi
 | |
| 
 | |
|   %val64 = fptosi fp128 %val to i64
 | |
|   store i64 %val64, i64* @var64
 | |
| ; CHECK: bl __fixtfdi
 | |
| 
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define void @test_fptoui() {
 | |
| ; CHECK: test_fptoui:
 | |
|   %val = load fp128* @lhs
 | |
| 
 | |
|   %val32 = fptoui fp128 %val to i32
 | |
|   store i32 %val32, i32* @var32
 | |
| ; CHECK: bl __fixunstfsi
 | |
| 
 | |
|   %val64 = fptoui fp128 %val to i64
 | |
|   store i64 %val64, i64* @var64
 | |
| ; CHECK: bl __fixunstfdi
 | |
| 
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define void @test_sitofp() {
 | |
| ; CHECK: test_sitofp:
 | |
| 
 | |
|   %src32 = load i32* @var32
 | |
|   %val32 = sitofp i32 %src32 to fp128
 | |
|   store volatile fp128 %val32, fp128* @lhs
 | |
| ; CHECK: bl __floatsitf
 | |
| 
 | |
|   %src64 = load i64* @var64
 | |
|   %val64 = sitofp i64 %src64 to fp128
 | |
|   store volatile fp128 %val64, fp128* @lhs
 | |
| ; CHECK: bl __floatditf
 | |
| 
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define void @test_uitofp() {
 | |
| ; CHECK: test_uitofp:
 | |
| 
 | |
|   %src32 = load i32* @var32
 | |
|   %val32 = uitofp i32 %src32 to fp128
 | |
|   store volatile fp128 %val32, fp128* @lhs
 | |
| ; CHECK: bl __floatunsitf
 | |
| 
 | |
|   %src64 = load i64* @var64
 | |
|   %val64 = uitofp i64 %src64 to fp128
 | |
|   store volatile fp128 %val64, fp128* @lhs
 | |
| ; CHECK: bl __floatunditf
 | |
| 
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define i1 @test_setcc1() {
 | |
| ; CHECK: test_setcc1:
 | |
| 
 | |
|   %lhs = load fp128* @lhs
 | |
|   %rhs = load fp128* @rhs
 | |
| ; CHECK: ldr q0, [{{x[0-9]+}}, #:lo12:lhs]
 | |
| ; CHECK: ldr q1, [{{x[0-9]+}}, #:lo12:rhs]
 | |
| 
 | |
| ; Technically, everything after the call to __letf2 is redundant, but we'll let
 | |
| ; LLVM have its fun for now.
 | |
|   %val = fcmp ole fp128 %lhs, %rhs
 | |
| ; CHECK: bl __letf2
 | |
| ; CHECK: cmp w0, #0
 | |
| ; CHECK: csinc w0, wzr, wzr, gt
 | |
| 
 | |
|   ret i1 %val
 | |
| ; CHECK: ret
 | |
| }
 | |
| 
 | |
| define i1 @test_setcc2() {
 | |
| ; CHECK: test_setcc2:
 | |
| 
 | |
|   %lhs = load fp128* @lhs
 | |
|   %rhs = load fp128* @rhs
 | |
| ; CHECK: ldr q0, [{{x[0-9]+}}, #:lo12:lhs]
 | |
| ; CHECK: ldr q1, [{{x[0-9]+}}, #:lo12:rhs]
 | |
| 
 | |
| ; Technically, everything after the call to __letf2 is redundant, but we'll let
 | |
| ; LLVM have its fun for now.
 | |
|   %val = fcmp ugt fp128 %lhs, %rhs
 | |
| ; CHECK: bl      __unordtf2
 | |
| ; CHECK: mov     x[[UNORDERED:[0-9]+]], x0
 | |
| 
 | |
| ; CHECK: bl      __gttf2
 | |
| ; CHECK: cmp w0, #0
 | |
| ; CHECK: csinc   [[GT:w[0-9]+]], wzr, wzr, le
 | |
| ; CHECK: cmp w[[UNORDERED]], #0
 | |
| ; CHECK: csinc   [[UNORDERED:w[0-9]+]], wzr, wzr, eq
 | |
| ; CHECK: orr     w0, [[UNORDERED]], [[GT]]
 | |
| 
 | |
|   ret i1 %val
 | |
| ; CHECK: ret
 | |
| }
 | |
| 
 | |
| define i32 @test_br_cc() {
 | |
| ; CHECK: test_br_cc:
 | |
| 
 | |
|   %lhs = load fp128* @lhs
 | |
|   %rhs = load fp128* @rhs
 | |
| ; CHECK: ldr q0, [{{x[0-9]+}}, #:lo12:lhs]
 | |
| ; CHECK: ldr q1, [{{x[0-9]+}}, #:lo12:rhs]
 | |
| 
 | |
|   ; olt == !uge, which LLVM unfortunately "optimizes" this to.
 | |
|   %cond = fcmp olt fp128 %lhs, %rhs
 | |
| ; CHECK: bl      __unordtf2
 | |
| ; CHECK: mov     x[[UNORDERED:[0-9]+]], x0
 | |
| 
 | |
| ; CHECK: bl      __getf2
 | |
| ; CHECK: cmp w0, #0
 | |
| 
 | |
| ; CHECK: csinc   [[OGE:w[0-9]+]], wzr, wzr, lt
 | |
| ; CHECK: cmp w[[UNORDERED]], #0
 | |
| ; CHECK: csinc   [[UNORDERED:w[0-9]+]], wzr, wzr, eq
 | |
| ; CHECK: orr     [[UGE:w[0-9]+]], [[UNORDERED]], [[OGE]]
 | |
| ; CHECK: cbnz [[UGE]], [[RET29:.LBB[0-9]+_[0-9]+]]
 | |
|   br i1 %cond, label %iftrue, label %iffalse
 | |
| 
 | |
| iftrue:
 | |
|   ret i32 42
 | |
| ; CHECK-NEXT: BB#
 | |
| ; CHECK-NEXT: movz x0, #42
 | |
| ; CHECK-NEXT: b [[REALRET:.LBB[0-9]+_[0-9]+]]
 | |
| 
 | |
| iffalse:
 | |
|   ret i32 29
 | |
| ; CHECK: [[RET29]]:
 | |
| ; CHECK-NEXT: movz x0, #29
 | |
| ; CHECK-NEXT: [[REALRET]]:
 | |
| ; CHECK: ret
 | |
| }
 | |
| 
 | |
| define void @test_select(i1 %cond, fp128 %lhs, fp128 %rhs) {
 | |
| ; CHECK: test_select:
 | |
| 
 | |
|   %val = select i1 %cond, fp128 %lhs, fp128 %rhs
 | |
|   store fp128 %val, fp128* @lhs
 | |
| ; CHECK: cmp w0, #0
 | |
| ; CHECK: str q1, [sp]
 | |
| ; CHECK-NEXT: b.eq [[IFFALSE:.LBB[0-9]+_[0-9]+]]
 | |
| ; CHECK-NEXT: BB#
 | |
| ; CHECK-NEXT: str q0, [sp]
 | |
| ; CHECK-NEXT: [[IFFALSE]]:
 | |
| ; CHECK-NEXT: ldr q0, [sp]
 | |
| ; CHECK: str q0, [{{x[0-9]+}}, #:lo12:lhs]
 | |
|   ret void
 | |
| ; CHECK: ret
 | |
| }
 | |
| 
 | |
| @varfloat = global float 0.0
 | |
| @vardouble = global double 0.0
 | |
| 
 | |
| define void @test_round() {
 | |
| ; CHECK: test_round:
 | |
| 
 | |
|   %val = load fp128* @lhs
 | |
| 
 | |
|   %float = fptrunc fp128 %val to float
 | |
|   store float %float, float* @varfloat
 | |
| ; CHECK: bl __trunctfsf2
 | |
| ; CHECK: str s0, [{{x[0-9]+}}, #:lo12:varfloat]
 | |
| 
 | |
|   %double = fptrunc fp128 %val to double
 | |
|   store double %double, double* @vardouble
 | |
| ; CHECK: bl __trunctfdf2
 | |
| ; CHECK: str d0, [{{x[0-9]+}}, #:lo12:vardouble]
 | |
| 
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define void @test_extend() {
 | |
| ; CHECK: test_extend:
 | |
| 
 | |
|   %val = load fp128* @lhs
 | |
| 
 | |
|   %float = load float* @varfloat
 | |
|   %fromfloat = fpext float %float to fp128
 | |
|   store volatile fp128 %fromfloat, fp128* @lhs
 | |
| ; CHECK: bl __extendsftf2
 | |
| ; CHECK: str q0, [{{x[0-9]+}}, #:lo12:lhs]
 | |
| 
 | |
|   %double = load double* @vardouble
 | |
|   %fromdouble = fpext double %double to fp128
 | |
|   store volatile fp128 %fromdouble, fp128* @lhs
 | |
| ; CHECK: bl __extenddftf2
 | |
| ; CHECK: str q0, [{{x[0-9]+}}, #:lo12:lhs]
 | |
| 
 | |
|   ret void
 | |
| ; CHECK: ret
 | |
| }
 | |
| 
 | |
| define fp128 @test_neg(fp128 %in) {
 | |
| ; CHECK: [[MINUS0:.LCPI[0-9]+_0]]:
 | |
| ; Make sure the weird hex constant below *is* -0.0
 | |
| ; CHECK-NEXT: fp128 -0
 | |
| 
 | |
| ; CHECK: test_neg:
 | |
| 
 | |
|   ; Could in principle be optimized to fneg which we can't select, this makes
 | |
|   ; sure that doesn't happen.
 | |
|   %ret = fsub fp128 0xL00000000000000008000000000000000, %in
 | |
| ; CHECK: str q0, [sp, #-16]
 | |
| ; CHECK-NEXT: ldr q1, [sp], #16
 | |
| ; CHECK: ldr q0, [{{x[0-9]+}}, #:lo12:[[MINUS0]]]
 | |
| ; CHECK: bl __subtf3
 | |
| 
 | |
|   ret fp128 %ret
 | |
| ; CHECK: ret
 | |
| }
 |