2016-12-06 06:40:13 +08:00
|
|
|
; RUN: llc -O0 -aarch64-enable-atomic-cfg-tidy=0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s
|
2016-08-03 03:04:29 +08:00
|
|
|
|
2016-03-08 09:48:08 +08:00
|
|
|
; This file checks that the translation from llvm IR to generic MachineInstr
|
|
|
|
; is correct.
|
|
|
|
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
|
2016-10-14 18:19:40 +08:00
|
|
|
target triple = "aarch64--"
|
2016-03-08 09:48:08 +08:00
|
|
|
|
|
|
|
; Tests for add.
|
2016-07-26 05:01:29 +08:00
|
|
|
; CHECK-LABEL: name: addi64
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s64) = COPY %x0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s64) = COPY %x1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s64) = G_ADD [[ARG1]], [[ARG2]]
|
2016-03-08 09:48:08 +08:00
|
|
|
; CHECK-NEXT: %x0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %x0
|
|
|
|
define i64 @addi64(i64 %arg1, i64 %arg2) {
|
|
|
|
%res = add i64 %arg1, %arg2
|
|
|
|
ret i64 %res
|
|
|
|
}
|
2016-03-12 01:28:03 +08:00
|
|
|
|
2016-08-05 05:39:44 +08:00
|
|
|
; CHECK-LABEL: name: muli64
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s64) = COPY %x0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s64) = COPY %x1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s64) = G_MUL [[ARG1]], [[ARG2]]
|
2016-08-05 05:39:44 +08:00
|
|
|
; CHECK-NEXT: %x0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %x0
|
|
|
|
define i64 @muli64(i64 %arg1, i64 %arg2) {
|
|
|
|
%res = mul i64 %arg1, %arg2
|
|
|
|
ret i64 %res
|
|
|
|
}
|
|
|
|
|
2016-07-23 00:59:52 +08:00
|
|
|
; Tests for alloca
|
2016-07-26 05:01:29 +08:00
|
|
|
; CHECK-LABEL: name: allocai64
|
2016-07-23 00:59:52 +08:00
|
|
|
; CHECK: stack:
|
|
|
|
; CHECK-NEXT: - { id: 0, name: ptr1, offset: 0, size: 8, alignment: 8 }
|
|
|
|
; CHECK-NEXT: - { id: 1, name: ptr2, offset: 0, size: 8, alignment: 1 }
|
|
|
|
; CHECK-NEXT: - { id: 2, name: ptr3, offset: 0, size: 128, alignment: 8 }
|
2016-07-28 01:47:54 +08:00
|
|
|
; CHECK-NEXT: - { id: 3, name: ptr4, offset: 0, size: 1, alignment: 8 }
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: %{{[0-9]+}}(p0) = G_FRAME_INDEX %stack.0.ptr1
|
|
|
|
; CHECK: %{{[0-9]+}}(p0) = G_FRAME_INDEX %stack.1.ptr2
|
|
|
|
; CHECK: %{{[0-9]+}}(p0) = G_FRAME_INDEX %stack.2.ptr3
|
|
|
|
; CHECK: %{{[0-9]+}}(p0) = G_FRAME_INDEX %stack.3.ptr4
|
2016-07-23 00:59:52 +08:00
|
|
|
define void @allocai64() {
|
|
|
|
%ptr1 = alloca i64
|
|
|
|
%ptr2 = alloca i64, align 1
|
|
|
|
%ptr3 = alloca i64, i32 16
|
2016-07-28 01:47:54 +08:00
|
|
|
%ptr4 = alloca [0 x i64]
|
2016-07-23 00:59:52 +08:00
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
2016-03-12 01:28:03 +08:00
|
|
|
; Tests for br.
|
2016-07-26 05:01:29 +08:00
|
|
|
; CHECK-LABEL: name: uncondbr
|
2016-03-12 01:28:03 +08:00
|
|
|
; CHECK: body:
|
|
|
|
;
|
|
|
|
; Entry basic block.
|
|
|
|
; CHECK: {{[0-9a-zA-Z._-]+}}:
|
|
|
|
;
|
|
|
|
; Make sure we have one successor and only one.
|
2016-11-21 21:15:38 +08:00
|
|
|
; CHECK-NEXT: successors: %[[END:[0-9a-zA-Z._-]+]](0x80000000)
|
2016-03-12 01:28:03 +08:00
|
|
|
;
|
|
|
|
; Check that we emit the correct branch.
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: G_BR %[[END]]
|
2016-03-12 01:28:03 +08:00
|
|
|
;
|
|
|
|
; Check that end contains the return instruction.
|
|
|
|
; CHECK: [[END]]:
|
|
|
|
; CHECK-NEXT: RET_ReallyLR
|
|
|
|
define void @uncondbr() {
|
|
|
|
br label %end
|
|
|
|
end:
|
|
|
|
ret void
|
|
|
|
}
|
2016-06-11 04:50:35 +08:00
|
|
|
|
2016-07-30 01:58:00 +08:00
|
|
|
; Tests for conditional br.
|
|
|
|
; CHECK-LABEL: name: condbr
|
|
|
|
; CHECK: body:
|
|
|
|
;
|
|
|
|
; Entry basic block.
|
|
|
|
; CHECK: {{[0-9a-zA-Z._-]+}}:
|
|
|
|
;
|
|
|
|
; Make sure we have two successors
|
2016-11-21 21:15:38 +08:00
|
|
|
; CHECK-NEXT: successors: %[[TRUE:[0-9a-zA-Z._-]+]](0x40000000),
|
|
|
|
; CHECK: %[[FALSE:[0-9a-zA-Z._-]+]](0x40000000)
|
2016-07-30 01:58:00 +08:00
|
|
|
;
|
|
|
|
; Check that we emit the correct branch.
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ADDR:%.*]](p0) = COPY %x0
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[TST:%.*]](s1) = G_LOAD [[ADDR]](p0)
|
|
|
|
; CHECK: G_BRCOND [[TST]](s1), %[[TRUE]]
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: G_BR %[[FALSE]]
|
2016-07-30 01:58:00 +08:00
|
|
|
;
|
|
|
|
; Check that each successor contains the return instruction.
|
|
|
|
; CHECK: [[TRUE]]:
|
|
|
|
; CHECK-NEXT: RET_ReallyLR
|
|
|
|
; CHECK: [[FALSE]]:
|
|
|
|
; CHECK-NEXT: RET_ReallyLR
|
|
|
|
define void @condbr(i1* %tstaddr) {
|
|
|
|
%tst = load i1, i1* %tstaddr
|
|
|
|
br i1 %tst, label %true, label %false
|
|
|
|
true:
|
|
|
|
ret void
|
|
|
|
false:
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
2016-06-11 04:50:35 +08:00
|
|
|
; Tests for or.
|
2016-07-26 05:01:29 +08:00
|
|
|
; CHECK-LABEL: name: ori64
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s64) = COPY %x0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s64) = COPY %x1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s64) = G_OR [[ARG1]], [[ARG2]]
|
2016-06-11 04:50:35 +08:00
|
|
|
; CHECK-NEXT: %x0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %x0
|
|
|
|
define i64 @ori64(i64 %arg1, i64 %arg2) {
|
|
|
|
%res = or i64 %arg1, %arg2
|
|
|
|
ret i64 %res
|
|
|
|
}
|
|
|
|
|
2016-07-26 05:01:29 +08:00
|
|
|
; CHECK-LABEL: name: ori32
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s32) = G_OR [[ARG1]], [[ARG2]]
|
2016-06-11 04:50:35 +08:00
|
|
|
; CHECK-NEXT: %w0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %w0
|
|
|
|
define i32 @ori32(i32 %arg1, i32 %arg2) {
|
|
|
|
%res = or i32 %arg1, %arg2
|
|
|
|
ret i32 %res
|
|
|
|
}
|
2016-07-21 23:50:42 +08:00
|
|
|
|
2016-07-30 00:56:20 +08:00
|
|
|
; Tests for xor.
|
|
|
|
; CHECK-LABEL: name: xori64
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s64) = COPY %x0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s64) = COPY %x1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s64) = G_XOR [[ARG1]], [[ARG2]]
|
2016-07-30 00:56:20 +08:00
|
|
|
; CHECK-NEXT: %x0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %x0
|
|
|
|
define i64 @xori64(i64 %arg1, i64 %arg2) {
|
|
|
|
%res = xor i64 %arg1, %arg2
|
|
|
|
ret i64 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: xori32
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s32) = G_XOR [[ARG1]], [[ARG2]]
|
2016-07-30 00:56:20 +08:00
|
|
|
; CHECK-NEXT: %w0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %w0
|
|
|
|
define i32 @xori32(i32 %arg1, i32 %arg2) {
|
|
|
|
%res = xor i32 %arg1, %arg2
|
|
|
|
ret i32 %res
|
|
|
|
}
|
|
|
|
|
2016-07-21 23:50:42 +08:00
|
|
|
; Tests for and.
|
2016-07-26 05:01:29 +08:00
|
|
|
; CHECK-LABEL: name: andi64
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s64) = COPY %x0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s64) = COPY %x1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s64) = G_AND [[ARG1]], [[ARG2]]
|
2016-07-21 23:50:42 +08:00
|
|
|
; CHECK-NEXT: %x0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %x0
|
|
|
|
define i64 @andi64(i64 %arg1, i64 %arg2) {
|
|
|
|
%res = and i64 %arg1, %arg2
|
|
|
|
ret i64 %res
|
|
|
|
}
|
|
|
|
|
2016-07-26 05:01:29 +08:00
|
|
|
; CHECK-LABEL: name: andi32
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s32) = G_AND [[ARG1]], [[ARG2]]
|
2016-07-21 23:50:42 +08:00
|
|
|
; CHECK-NEXT: %w0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %w0
|
|
|
|
define i32 @andi32(i32 %arg1, i32 %arg2) {
|
|
|
|
%res = and i32 %arg1, %arg2
|
|
|
|
ret i32 %res
|
|
|
|
}
|
2016-07-22 01:26:50 +08:00
|
|
|
|
|
|
|
; Tests for sub.
|
2016-07-26 05:01:29 +08:00
|
|
|
; CHECK-LABEL: name: subi64
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s64) = COPY %x0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s64) = COPY %x1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s64) = G_SUB [[ARG1]], [[ARG2]]
|
2016-07-22 01:26:50 +08:00
|
|
|
; CHECK-NEXT: %x0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %x0
|
|
|
|
define i64 @subi64(i64 %arg1, i64 %arg2) {
|
|
|
|
%res = sub i64 %arg1, %arg2
|
|
|
|
ret i64 %res
|
|
|
|
}
|
|
|
|
|
2016-07-26 05:01:29 +08:00
|
|
|
; CHECK-LABEL: name: subi32
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s32) = G_SUB [[ARG1]], [[ARG2]]
|
2016-07-22 01:26:50 +08:00
|
|
|
; CHECK-NEXT: %w0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %w0
|
|
|
|
define i32 @subi32(i32 %arg1, i32 %arg2) {
|
|
|
|
%res = sub i32 %arg1, %arg2
|
|
|
|
ret i32 %res
|
|
|
|
}
|
2016-07-26 05:01:29 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: name: ptrtoint
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](p0) = COPY %x0
|
|
|
|
; CHECK: [[RES:%[0-9]+]](s64) = G_PTRTOINT [[ARG1]]
|
2016-07-26 05:01:29 +08:00
|
|
|
; CHECK: %x0 = COPY [[RES]]
|
|
|
|
; CHECK: RET_ReallyLR implicit %x0
|
|
|
|
define i64 @ptrtoint(i64* %a) {
|
|
|
|
%val = ptrtoint i64* %a to i64
|
|
|
|
ret i64 %val
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: inttoptr
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s64) = COPY %x0
|
|
|
|
; CHECK: [[RES:%[0-9]+]](p0) = G_INTTOPTR [[ARG1]]
|
2016-07-26 05:01:29 +08:00
|
|
|
; CHECK: %x0 = COPY [[RES]]
|
|
|
|
; CHECK: RET_ReallyLR implicit %x0
|
|
|
|
define i64* @inttoptr(i64 %a) {
|
|
|
|
%val = inttoptr i64 %a to i64*
|
|
|
|
ret i64* %val
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: trivial_bitcast
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](p0) = COPY %x0
|
2016-08-11 00:51:14 +08:00
|
|
|
; CHECK: %x0 = COPY [[ARG1]]
|
2016-07-26 05:01:29 +08:00
|
|
|
; CHECK: RET_ReallyLR implicit %x0
|
|
|
|
define i64* @trivial_bitcast(i8* %a) {
|
|
|
|
%val = bitcast i8* %a to i64*
|
|
|
|
ret i64* %val
|
|
|
|
}
|
|
|
|
|
2016-08-11 00:51:14 +08:00
|
|
|
; CHECK-LABEL: name: trivial_bitcast_with_copy
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[A:%[0-9]+]](p0) = COPY %x0
|
|
|
|
; CHECK: G_BR %[[CAST:bb\.[0-9]+]]
|
2016-08-11 00:51:14 +08:00
|
|
|
|
|
|
|
; CHECK: [[CAST]]:
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: {{%[0-9]+}}(p0) = COPY [[A]]
|
|
|
|
; CHECK: G_BR %[[END:bb\.[0-9]+]]
|
2016-08-11 00:51:14 +08:00
|
|
|
|
|
|
|
; CHECK: [[END]]:
|
|
|
|
define i64* @trivial_bitcast_with_copy(i8* %a) {
|
|
|
|
br label %cast
|
|
|
|
|
|
|
|
end:
|
|
|
|
ret i64* %val
|
|
|
|
|
|
|
|
cast:
|
|
|
|
%val = bitcast i8* %a to i64*
|
|
|
|
br label %end
|
|
|
|
}
|
|
|
|
|
2016-07-26 05:01:29 +08:00
|
|
|
; CHECK-LABEL: name: bitcast
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s64) = COPY %x0
|
|
|
|
; CHECK: [[RES1:%[0-9]+]](<2 x s32>) = G_BITCAST [[ARG1]]
|
|
|
|
; CHECK: [[RES2:%[0-9]+]](s64) = G_BITCAST [[RES1]]
|
2016-07-26 05:01:29 +08:00
|
|
|
; CHECK: %x0 = COPY [[RES2]]
|
|
|
|
; CHECK: RET_ReallyLR implicit %x0
|
|
|
|
define i64 @bitcast(i64 %a) {
|
|
|
|
%res1 = bitcast i64 %a to <2 x i32>
|
|
|
|
%res2 = bitcast <2 x i32> %res1 to i64
|
|
|
|
ret i64 %res2
|
|
|
|
}
|
2016-07-27 04:23:26 +08:00
|
|
|
|
2016-08-05 02:35:17 +08:00
|
|
|
; CHECK-LABEL: name: trunc
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s64) = COPY %x0
|
|
|
|
; CHECK: [[VEC:%[0-9]+]](<4 x s32>) = G_LOAD
|
|
|
|
; CHECK: [[RES1:%[0-9]+]](s8) = G_TRUNC [[ARG1]]
|
|
|
|
; CHECK: [[RES2:%[0-9]+]](<4 x s16>) = G_TRUNC [[VEC]]
|
2016-08-05 02:35:17 +08:00
|
|
|
define void @trunc(i64 %a) {
|
|
|
|
%vecptr = alloca <4 x i32>
|
|
|
|
%vec = load <4 x i32>, <4 x i32>* %vecptr
|
|
|
|
%res1 = trunc i64 %a to i8
|
|
|
|
%res2 = trunc <4 x i32> %vec to <4 x i16>
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
2016-07-27 04:23:26 +08:00
|
|
|
; CHECK-LABEL: name: load
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x0
|
|
|
|
; CHECK: [[ADDR42:%[0-9]+]](p42) = COPY %x1
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[VAL1:%[0-9]+]](s64) = G_LOAD [[ADDR]](p0) :: (load 8 from %ir.addr, align 16)
|
|
|
|
; CHECK: [[VAL2:%[0-9]+]](s64) = G_LOAD [[ADDR42]](p42) :: (load 8 from %ir.addr42)
|
2016-10-19 23:55:06 +08:00
|
|
|
; CHECK: [[SUM2:%.*]](s64) = G_ADD [[VAL1]], [[VAL2]]
|
|
|
|
; CHECK: [[VAL3:%[0-9]+]](s64) = G_LOAD [[ADDR]](p0) :: (volatile load 8 from %ir.addr)
|
|
|
|
; CHECK: [[SUM3:%[0-9]+]](s64) = G_ADD [[SUM2]], [[VAL3]]
|
|
|
|
; CHECK: %x0 = COPY [[SUM3]]
|
2016-07-27 04:23:26 +08:00
|
|
|
; CHECK: RET_ReallyLR implicit %x0
|
|
|
|
define i64 @load(i64* %addr, i64 addrspace(42)* %addr42) {
|
|
|
|
%val1 = load i64, i64* %addr, align 16
|
2016-10-19 23:55:06 +08:00
|
|
|
|
2016-07-27 04:23:26 +08:00
|
|
|
%val2 = load i64, i64 addrspace(42)* %addr42
|
2016-10-19 23:55:06 +08:00
|
|
|
%sum2 = add i64 %val1, %val2
|
|
|
|
|
|
|
|
%val3 = load volatile i64, i64* %addr
|
|
|
|
%sum3 = add i64 %sum2, %val3
|
|
|
|
ret i64 %sum3
|
2016-07-27 04:23:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: store
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x0
|
|
|
|
; CHECK: [[ADDR42:%[0-9]+]](p42) = COPY %x1
|
|
|
|
; CHECK: [[VAL1:%[0-9]+]](s64) = COPY %x2
|
|
|
|
; CHECK: [[VAL2:%[0-9]+]](s64) = COPY %x3
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: G_STORE [[VAL1]](s64), [[ADDR]](p0) :: (store 8 into %ir.addr, align 16)
|
|
|
|
; CHECK: G_STORE [[VAL2]](s64), [[ADDR42]](p42) :: (store 8 into %ir.addr42)
|
2016-10-19 23:55:06 +08:00
|
|
|
; CHECK: G_STORE [[VAL1]](s64), [[ADDR]](p0) :: (volatile store 8 into %ir.addr)
|
2016-07-27 04:23:26 +08:00
|
|
|
; CHECK: RET_ReallyLR
|
|
|
|
define void @store(i64* %addr, i64 addrspace(42)* %addr42, i64 %val1, i64 %val2) {
|
|
|
|
store i64 %val1, i64* %addr, align 16
|
|
|
|
store i64 %val2, i64 addrspace(42)* %addr42
|
2016-10-19 23:55:06 +08:00
|
|
|
store volatile i64 %val1, i64* %addr
|
2016-07-27 04:23:26 +08:00
|
|
|
%sum = add i64 %val1, %val2
|
|
|
|
ret void
|
|
|
|
}
|
2016-07-30 06:32:36 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: name: intrinsics
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[CUR:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK: [[BITS:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK: [[PTR:%[0-9]+]](p0) = G_INTRINSIC intrinsic(@llvm.returnaddress), 0
|
|
|
|
; CHECK: [[PTR_VEC:%[0-9]+]](p0) = G_FRAME_INDEX %stack.0.ptr.vec
|
|
|
|
; CHECK: [[VEC:%[0-9]+]](<8 x s8>) = G_LOAD [[PTR_VEC]]
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.neon.st2), [[VEC]](<8 x s8>), [[VEC]](<8 x s8>), [[PTR]](p0)
|
2016-07-30 06:32:36 +08:00
|
|
|
; CHECK: RET_ReallyLR
|
|
|
|
declare i8* @llvm.returnaddress(i32)
|
|
|
|
declare void @llvm.aarch64.neon.st2.v8i8.p0i8(<8 x i8>, <8 x i8>, i8*)
|
|
|
|
declare { <8 x i8>, <8 x i8> } @llvm.aarch64.neon.ld2.v8i8.p0v8i8(<8 x i8>*)
|
|
|
|
define void @intrinsics(i32 %cur, i32 %bits) {
|
|
|
|
%ptr = call i8* @llvm.returnaddress(i32 0)
|
|
|
|
%ptr.vec = alloca <8 x i8>
|
|
|
|
%vec = load <8 x i8>, <8 x i8>* %ptr.vec
|
|
|
|
call void @llvm.aarch64.neon.st2.v8i8.p0i8(<8 x i8> %vec, <8 x i8> %vec, i8* %ptr)
|
|
|
|
ret void
|
|
|
|
}
|
2016-07-30 06:41:55 +08:00
|
|
|
|
2016-08-06 01:16:40 +08:00
|
|
|
; CHECK-LABEL: name: test_phi
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: G_BRCOND {{%.*}}, %[[TRUE:bb\.[0-9]+]]
|
|
|
|
; CHECK: G_BR %[[FALSE:bb\.[0-9]+]]
|
2016-08-06 01:16:40 +08:00
|
|
|
|
|
|
|
; CHECK: [[TRUE]]:
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[RES1:%[0-9]+]](s32) = G_LOAD
|
2016-08-06 01:16:40 +08:00
|
|
|
|
|
|
|
; CHECK: [[FALSE]]:
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[RES2:%[0-9]+]](s32) = G_LOAD
|
2016-08-06 01:16:40 +08:00
|
|
|
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[RES:%[0-9]+]](s32) = PHI [[RES1]](s32), %[[TRUE]], [[RES2]](s32), %[[FALSE]]
|
2016-08-06 01:16:40 +08:00
|
|
|
; CHECK: %w0 = COPY [[RES]]
|
|
|
|
define i32 @test_phi(i32* %addr1, i32* %addr2, i1 %tst) {
|
|
|
|
br i1 %tst, label %true, label %false
|
|
|
|
|
|
|
|
true:
|
|
|
|
%res1 = load i32, i32* %addr1
|
|
|
|
br label %end
|
|
|
|
|
|
|
|
false:
|
|
|
|
%res2 = load i32, i32* %addr2
|
|
|
|
br label %end
|
|
|
|
|
|
|
|
end:
|
|
|
|
%res = phi i32 [%res1, %true], [%res2, %false]
|
|
|
|
ret i32 %res
|
|
|
|
}
|
2016-08-06 01:50:36 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: name: unreachable
|
|
|
|
; CHECK: G_ADD
|
|
|
|
; CHECK-NEXT: {{^$}}
|
|
|
|
; CHECK-NEXT: ...
|
|
|
|
define void @unreachable(i32 %a) {
|
|
|
|
%sum = add i32 %a, %a
|
|
|
|
unreachable
|
|
|
|
}
|
2016-08-10 05:28:04 +08:00
|
|
|
|
|
|
|
; It's important that constants are after argument passing, but before the
|
|
|
|
; rest of the entry block.
|
|
|
|
; CHECK-LABEL: name: constant_int
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[IN:%[0-9]+]](s32) = COPY %w0
|
2016-12-06 05:47:07 +08:00
|
|
|
; CHECK: [[ONE:%[0-9]+]](s32) = G_CONSTANT i32 1
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: G_BR
|
2016-08-10 05:28:04 +08:00
|
|
|
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[SUM1:%[0-9]+]](s32) = G_ADD [[IN]], [[ONE]]
|
|
|
|
; CHECK: [[SUM2:%[0-9]+]](s32) = G_ADD [[IN]], [[ONE]]
|
|
|
|
; CHECK: [[RES:%[0-9]+]](s32) = G_ADD [[SUM1]], [[SUM2]]
|
2016-08-10 05:28:04 +08:00
|
|
|
; CHECK: %w0 = COPY [[RES]]
|
|
|
|
|
|
|
|
define i32 @constant_int(i32 %in) {
|
|
|
|
br label %next
|
|
|
|
|
|
|
|
next:
|
|
|
|
%sum1 = add i32 %in, 1
|
|
|
|
%sum2 = add i32 %in, 1
|
|
|
|
%res = add i32 %sum1, %sum2
|
|
|
|
ret i32 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: constant_int_start
|
2016-12-06 05:47:07 +08:00
|
|
|
; CHECK: [[ANSWER:%[0-9]+]](s32) = G_CONSTANT i32 42
|
2016-12-06 06:40:13 +08:00
|
|
|
; CHECK: [[TWO:%[0-9]+]](s32) = G_CONSTANT i32 2
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[RES:%[0-9]+]](s32) = G_ADD [[TWO]], [[ANSWER]]
|
2016-08-10 05:28:04 +08:00
|
|
|
define i32 @constant_int_start() {
|
|
|
|
%res = add i32 2, 42
|
|
|
|
ret i32 %res
|
|
|
|
}
|
2016-08-10 07:01:30 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_undef
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[UNDEF:%[0-9]+]](s32) = IMPLICIT_DEF
|
2016-08-10 07:01:30 +08:00
|
|
|
; CHECK: %w0 = COPY [[UNDEF]]
|
|
|
|
define i32 @test_undef() {
|
|
|
|
ret i32 undef
|
|
|
|
}
|
2016-08-11 07:02:41 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_constant_inttoptr
|
2016-12-06 05:47:07 +08:00
|
|
|
; CHECK: [[ONE:%[0-9]+]](s64) = G_CONSTANT i64 1
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[PTR:%[0-9]+]](p0) = G_INTTOPTR [[ONE]]
|
2016-08-11 07:02:41 +08:00
|
|
|
; CHECK: %x0 = COPY [[PTR]]
|
|
|
|
define i8* @test_constant_inttoptr() {
|
|
|
|
ret i8* inttoptr(i64 1 to i8*)
|
|
|
|
}
|
2016-08-12 00:21:29 +08:00
|
|
|
|
|
|
|
; This failed purely because the Constant -> VReg map was kept across
|
|
|
|
; functions, so reuse the "i64 1" from above.
|
|
|
|
; CHECK-LABEL: name: test_reused_constant
|
2016-12-06 05:47:07 +08:00
|
|
|
; CHECK: [[ONE:%[0-9]+]](s64) = G_CONSTANT i64 1
|
2016-08-12 00:21:29 +08:00
|
|
|
; CHECK: %x0 = COPY [[ONE]]
|
|
|
|
define i64 @test_reused_constant() {
|
|
|
|
ret i64 1
|
|
|
|
}
|
2016-08-12 05:01:10 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_sext
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[IN:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK: [[RES:%[0-9]+]](s64) = G_SEXT [[IN]]
|
2016-08-12 05:01:10 +08:00
|
|
|
; CHECK: %x0 = COPY [[RES]]
|
|
|
|
define i64 @test_sext(i32 %in) {
|
|
|
|
%res = sext i32 %in to i64
|
|
|
|
ret i64 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_zext
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[IN:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK: [[RES:%[0-9]+]](s64) = G_ZEXT [[IN]]
|
2016-08-12 05:01:10 +08:00
|
|
|
; CHECK: %x0 = COPY [[RES]]
|
|
|
|
define i64 @test_zext(i32 %in) {
|
|
|
|
%res = zext i32 %in to i64
|
|
|
|
ret i64 %res
|
|
|
|
}
|
2016-08-12 05:01:13 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_shl
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s32) = G_SHL [[ARG1]], [[ARG2]]
|
2016-08-12 05:01:13 +08:00
|
|
|
; CHECK-NEXT: %w0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %w0
|
|
|
|
define i32 @test_shl(i32 %arg1, i32 %arg2) {
|
|
|
|
%res = shl i32 %arg1, %arg2
|
|
|
|
ret i32 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_lshr
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s32) = G_LSHR [[ARG1]], [[ARG2]]
|
2016-08-12 05:01:13 +08:00
|
|
|
; CHECK-NEXT: %w0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %w0
|
|
|
|
define i32 @test_lshr(i32 %arg1, i32 %arg2) {
|
|
|
|
%res = lshr i32 %arg1, %arg2
|
|
|
|
ret i32 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_ashr
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s32) = G_ASHR [[ARG1]], [[ARG2]]
|
2016-08-12 05:01:13 +08:00
|
|
|
; CHECK-NEXT: %w0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %w0
|
|
|
|
define i32 @test_ashr(i32 %arg1, i32 %arg2) {
|
|
|
|
%res = ashr i32 %arg1, %arg2
|
|
|
|
ret i32 %res
|
|
|
|
}
|
2016-08-12 05:40:55 +08:00
|
|
|
|
2016-08-18 23:17:01 +08:00
|
|
|
; CHECK-LABEL: name: test_sdiv
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s32) = G_SDIV [[ARG1]], [[ARG2]]
|
2016-08-18 23:17:01 +08:00
|
|
|
; CHECK-NEXT: %w0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %w0
|
|
|
|
define i32 @test_sdiv(i32 %arg1, i32 %arg2) {
|
|
|
|
%res = sdiv i32 %arg1, %arg2
|
|
|
|
ret i32 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_udiv
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s32) = G_UDIV [[ARG1]], [[ARG2]]
|
2016-08-18 23:17:01 +08:00
|
|
|
; CHECK-NEXT: %w0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %w0
|
|
|
|
define i32 @test_udiv(i32 %arg1, i32 %arg2) {
|
|
|
|
%res = udiv i32 %arg1, %arg2
|
|
|
|
ret i32 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_srem
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s32) = G_SREM [[ARG1]], [[ARG2]]
|
2016-08-18 23:17:01 +08:00
|
|
|
; CHECK-NEXT: %w0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %w0
|
|
|
|
define i32 @test_srem(i32 %arg1, i32 %arg2) {
|
|
|
|
%res = srem i32 %arg1, %arg2
|
|
|
|
ret i32 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_urem
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s32) = G_UREM [[ARG1]], [[ARG2]]
|
2016-08-18 23:17:01 +08:00
|
|
|
; CHECK-NEXT: %w0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %w0
|
|
|
|
define i32 @test_urem(i32 %arg1, i32 %arg2) {
|
|
|
|
%res = urem i32 %arg1, %arg2
|
|
|
|
ret i32 %res
|
|
|
|
}
|
|
|
|
|
2016-08-12 05:40:55 +08:00
|
|
|
; CHECK-LABEL: name: test_constant_null
|
2016-12-06 05:47:07 +08:00
|
|
|
; CHECK: [[NULL:%[0-9]+]](p0) = G_CONSTANT i64 0
|
2016-08-12 05:40:55 +08:00
|
|
|
; CHECK: %x0 = COPY [[NULL]]
|
|
|
|
define i8* @test_constant_null() {
|
|
|
|
ret i8* null
|
|
|
|
}
|
2016-08-16 05:13:17 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_struct_memops
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x0
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[VAL:%[0-9]+]](s64) = G_LOAD [[ADDR]](p0) :: (load 8 from %ir.addr, align 4)
|
|
|
|
; CHECK: G_STORE [[VAL]](s64), [[ADDR]](p0) :: (store 8 into %ir.addr, align 4)
|
2016-08-16 05:13:17 +08:00
|
|
|
define void @test_struct_memops({ i8, i32 }* %addr) {
|
|
|
|
%val = load { i8, i32 }, { i8, i32 }* %addr
|
|
|
|
store { i8, i32 } %val, { i8, i32 }* %addr
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_i1_memops
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x0
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[VAL:%[0-9]+]](s1) = G_LOAD [[ADDR]](p0) :: (load 1 from %ir.addr)
|
|
|
|
; CHECK: G_STORE [[VAL]](s1), [[ADDR]](p0) :: (store 1 into %ir.addr)
|
2016-08-16 05:13:17 +08:00
|
|
|
define void @test_i1_memops(i1* %addr) {
|
|
|
|
%val = load i1, i1* %addr
|
|
|
|
store i1 %val, i1* %addr
|
|
|
|
ret void
|
|
|
|
}
|
2016-08-18 04:25:25 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: name: int_comparison
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[LHS:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK: [[RHS:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[TST:%[0-9]+]](s1) = G_ICMP intpred(ne), [[LHS]](s32), [[RHS]]
|
|
|
|
; CHECK: G_STORE [[TST]](s1), [[ADDR]](p0)
|
2016-08-18 04:25:25 +08:00
|
|
|
define void @int_comparison(i32 %a, i32 %b, i1* %addr) {
|
|
|
|
%res = icmp ne i32 %a, %b
|
|
|
|
store i1 %res, i1* %addr
|
|
|
|
ret void
|
|
|
|
}
|
2016-08-19 00:05:06 +08:00
|
|
|
|
2016-09-15 18:40:38 +08:00
|
|
|
; CHECK-LABEL: name: ptr_comparison
|
|
|
|
; CHECK: [[LHS:%[0-9]+]](p0) = COPY %x0
|
|
|
|
; CHECK: [[RHS:%[0-9]+]](p0) = COPY %x1
|
|
|
|
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2
|
|
|
|
; CHECK: [[TST:%[0-9]+]](s1) = G_ICMP intpred(eq), [[LHS]](p0), [[RHS]]
|
|
|
|
; CHECK: G_STORE [[TST]](s1), [[ADDR]](p0)
|
|
|
|
define void @ptr_comparison(i8* %a, i8* %b, i1* %addr) {
|
|
|
|
%res = icmp eq i8* %a, %b
|
|
|
|
store i1 %res, i1* %addr
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
2016-08-19 00:05:06 +08:00
|
|
|
; CHECK-LABEL: name: test_fadd
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %s0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s32) = COPY %s1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s32) = G_FADD [[ARG1]], [[ARG2]]
|
2016-08-19 00:05:06 +08:00
|
|
|
; CHECK-NEXT: %s0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %s0
|
|
|
|
define float @test_fadd(float %arg1, float %arg2) {
|
|
|
|
%res = fadd float %arg1, %arg2
|
|
|
|
ret float %res
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_fsub
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %s0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s32) = COPY %s1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s32) = G_FSUB [[ARG1]], [[ARG2]]
|
2016-08-19 00:05:06 +08:00
|
|
|
; CHECK-NEXT: %s0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %s0
|
|
|
|
define float @test_fsub(float %arg1, float %arg2) {
|
|
|
|
%res = fsub float %arg1, %arg2
|
|
|
|
ret float %res
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_fmul
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %s0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s32) = COPY %s1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s32) = G_FMUL [[ARG1]], [[ARG2]]
|
2016-08-19 00:05:06 +08:00
|
|
|
; CHECK-NEXT: %s0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %s0
|
|
|
|
define float @test_fmul(float %arg1, float %arg2) {
|
|
|
|
%res = fmul float %arg1, %arg2
|
|
|
|
ret float %res
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_fdiv
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %s0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s32) = COPY %s1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s32) = G_FDIV [[ARG1]], [[ARG2]]
|
2016-08-19 00:05:06 +08:00
|
|
|
; CHECK-NEXT: %s0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %s0
|
|
|
|
define float @test_fdiv(float %arg1, float %arg2) {
|
|
|
|
%res = fdiv float %arg1, %arg2
|
|
|
|
ret float %res
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_frem
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ARG1:%[0-9]+]](s32) = COPY %s0
|
|
|
|
; CHECK-NEXT: [[ARG2:%[0-9]+]](s32) = COPY %s1
|
|
|
|
; CHECK-NEXT: [[RES:%[0-9]+]](s32) = G_FREM [[ARG1]], [[ARG2]]
|
2016-08-19 00:05:06 +08:00
|
|
|
; CHECK-NEXT: %s0 = COPY [[RES]]
|
|
|
|
; CHECK-NEXT: RET_ReallyLR implicit %s0
|
|
|
|
define float @test_frem(float %arg1, float %arg2) {
|
|
|
|
%res = frem float %arg1, %arg2
|
|
|
|
ret float %res
|
|
|
|
}
|
2016-08-20 01:17:06 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_sadd_overflow
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[LHS:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK: [[RHS:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2
|
|
|
|
; CHECK: [[VAL:%[0-9]+]](s32), [[OVERFLOW:%[0-9]+]](s1) = G_SADDO [[LHS]], [[RHS]]
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[RES:%[0-9]+]](s64) = G_SEQUENCE [[VAL]](s32), 0, [[OVERFLOW]](s1), 32
|
|
|
|
; CHECK: G_STORE [[RES]](s64), [[ADDR]](p0)
|
2016-08-20 01:17:06 +08:00
|
|
|
declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32)
|
|
|
|
define void @test_sadd_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) {
|
|
|
|
%res = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %lhs, i32 %rhs)
|
|
|
|
store { i32, i1 } %res, { i32, i1 }* %addr
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_uadd_overflow
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[LHS:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK: [[RHS:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2
|
2016-12-06 05:47:07 +08:00
|
|
|
; CHECK: [[ZERO:%[0-9]+]](s1) = G_CONSTANT i1 false
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[VAL:%[0-9]+]](s32), [[OVERFLOW:%[0-9]+]](s1) = G_UADDE [[LHS]], [[RHS]], [[ZERO]]
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[RES:%[0-9]+]](s64) = G_SEQUENCE [[VAL]](s32), 0, [[OVERFLOW]](s1), 32
|
|
|
|
; CHECK: G_STORE [[RES]](s64), [[ADDR]](p0)
|
2016-08-20 01:17:06 +08:00
|
|
|
declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32)
|
|
|
|
define void @test_uadd_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) {
|
|
|
|
%res = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %lhs, i32 %rhs)
|
|
|
|
store { i32, i1 } %res, { i32, i1 }* %addr
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_ssub_overflow
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[LHS:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK: [[RHS:%[0-9]+]](s32) = COPY %w1
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[VAL:%[0-9]+]](s32), [[OVERFLOW:%[0-9]+]](s1) = G_SSUBO [[LHS]], [[RHS]]
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[RES:%[0-9]+]](s64) = G_SEQUENCE [[VAL]](s32), 0, [[OVERFLOW]](s1), 32
|
|
|
|
; CHECK: G_STORE [[RES]](s64), [[ADDR]](p0)
|
2016-08-20 01:17:06 +08:00
|
|
|
declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32)
|
|
|
|
define void @test_ssub_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %subr) {
|
|
|
|
%res = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %lhs, i32 %rhs)
|
|
|
|
store { i32, i1 } %res, { i32, i1 }* %subr
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_usub_overflow
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[LHS:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK: [[RHS:%[0-9]+]](s32) = COPY %w1
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2
|
2016-12-06 05:47:07 +08:00
|
|
|
; CHECK: [[ZERO:%[0-9]+]](s1) = G_CONSTANT i1 false
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[VAL:%[0-9]+]](s32), [[OVERFLOW:%[0-9]+]](s1) = G_USUBE [[LHS]], [[RHS]], [[ZERO]]
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[RES:%[0-9]+]](s64) = G_SEQUENCE [[VAL]](s32), 0, [[OVERFLOW]](s1), 32
|
|
|
|
; CHECK: G_STORE [[RES]](s64), [[ADDR]](p0)
|
2016-08-20 01:17:06 +08:00
|
|
|
declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32)
|
|
|
|
define void @test_usub_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %subr) {
|
|
|
|
%res = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %lhs, i32 %rhs)
|
|
|
|
store { i32, i1 } %res, { i32, i1 }* %subr
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_smul_overflow
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[LHS:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK: [[RHS:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2
|
|
|
|
; CHECK: [[VAL:%[0-9]+]](s32), [[OVERFLOW:%[0-9]+]](s1) = G_SMULO [[LHS]], [[RHS]]
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[RES:%[0-9]+]](s64) = G_SEQUENCE [[VAL]](s32), 0, [[OVERFLOW]](s1), 32
|
|
|
|
; CHECK: G_STORE [[RES]](s64), [[ADDR]](p0)
|
2016-08-20 01:17:06 +08:00
|
|
|
declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32)
|
|
|
|
define void @test_smul_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) {
|
|
|
|
%res = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %lhs, i32 %rhs)
|
|
|
|
store { i32, i1 } %res, { i32, i1 }* %addr
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_umul_overflow
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[LHS:%[0-9]+]](s32) = COPY %w0
|
|
|
|
; CHECK: [[RHS:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2
|
|
|
|
; CHECK: [[VAL:%[0-9]+]](s32), [[OVERFLOW:%[0-9]+]](s1) = G_UMULO [[LHS]], [[RHS]]
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[RES:%[0-9]+]](s64) = G_SEQUENCE [[VAL]](s32), 0, [[OVERFLOW]](s1), 32
|
|
|
|
; CHECK: G_STORE [[RES]](s64), [[ADDR]](p0)
|
2016-08-20 01:17:06 +08:00
|
|
|
declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32)
|
|
|
|
define void @test_umul_overflow(i32 %lhs, i32 %rhs, { i32, i1 }* %addr) {
|
|
|
|
%res = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %lhs, i32 %rhs)
|
|
|
|
store { i32, i1 } %res, { i32, i1 }* %addr
|
|
|
|
ret void
|
|
|
|
}
|
2016-08-20 01:47:05 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_extractvalue
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[STRUCT:%[0-9]+]](s128) = G_LOAD
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[RES:%[0-9]+]](s32) = G_EXTRACT [[STRUCT]](s128), 64
|
2016-08-20 01:47:05 +08:00
|
|
|
; CHECK: %w0 = COPY [[RES]]
|
|
|
|
%struct.nested = type {i8, { i8, i32 }, i32}
|
|
|
|
define i32 @test_extractvalue(%struct.nested* %addr) {
|
|
|
|
%struct = load %struct.nested, %struct.nested* %addr
|
|
|
|
%res = extractvalue %struct.nested %struct, 1, 1
|
|
|
|
ret i32 %res
|
|
|
|
}
|
2016-08-20 02:09:41 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_extractvalue_agg
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[STRUCT:%[0-9]+]](s128) = G_LOAD
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[RES:%[0-9]+]](s64) = G_EXTRACT [[STRUCT]](s128), 32
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: G_STORE [[RES]]
|
2016-08-20 02:09:41 +08:00
|
|
|
define void @test_extractvalue_agg(%struct.nested* %addr, {i8, i32}* %addr2) {
|
|
|
|
%struct = load %struct.nested, %struct.nested* %addr
|
|
|
|
%res = extractvalue %struct.nested %struct, 1
|
|
|
|
store {i8, i32} %res, {i8, i32}* %addr2
|
|
|
|
ret void
|
|
|
|
}
|
2016-08-20 04:08:55 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_insertvalue
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[VAL:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK: [[STRUCT:%[0-9]+]](s128) = G_LOAD
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[NEWSTRUCT:%[0-9]+]](s128) = G_INSERT [[STRUCT]](s128), [[VAL]](s32), 64
|
|
|
|
; CHECK: G_STORE [[NEWSTRUCT]](s128),
|
2016-08-20 04:08:55 +08:00
|
|
|
define void @test_insertvalue(%struct.nested* %addr, i32 %val) {
|
|
|
|
%struct = load %struct.nested, %struct.nested* %addr
|
|
|
|
%newstruct = insertvalue %struct.nested %struct, i32 %val, 1, 1
|
|
|
|
store %struct.nested %newstruct, %struct.nested* %addr
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_insertvalue_agg
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[SMALLSTRUCT:%[0-9]+]](s64) = G_LOAD
|
|
|
|
; CHECK: [[STRUCT:%[0-9]+]](s128) = G_LOAD
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[RES:%[0-9]+]](s128) = G_INSERT [[STRUCT]](s128), [[SMALLSTRUCT]](s64), 32
|
|
|
|
; CHECK: G_STORE [[RES]](s128)
|
2016-08-20 04:08:55 +08:00
|
|
|
define void @test_insertvalue_agg(%struct.nested* %addr, {i8, i32}* %addr2) {
|
|
|
|
%smallstruct = load {i8, i32}, {i8, i32}* %addr2
|
|
|
|
%struct = load %struct.nested, %struct.nested* %addr
|
|
|
|
%res = insertvalue %struct.nested %struct, {i8, i32} %smallstruct, 1
|
|
|
|
store %struct.nested %res, %struct.nested* %addr
|
|
|
|
ret void
|
|
|
|
}
|
2016-08-20 04:09:07 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_select
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[TST:%[0-9]+]](s1) = COPY %w0
|
|
|
|
; CHECK: [[LHS:%[0-9]+]](s32) = COPY %w1
|
|
|
|
; CHECK: [[RHS:%[0-9]+]](s32) = COPY %w2
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[RES:%[0-9]+]](s32) = G_SELECT [[TST]](s1), [[LHS]], [[RHS]]
|
2016-08-20 04:09:07 +08:00
|
|
|
; CHECK: %w0 = COPY [[RES]]
|
|
|
|
define i32 @test_select(i1 %tst, i32 %lhs, i32 %rhs) {
|
|
|
|
%res = select i1 %tst, i32 %lhs, i32 %rhs
|
|
|
|
ret i32 %res
|
|
|
|
}
|
2016-08-20 04:09:11 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_fptosi
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[FPADDR:%[0-9]+]](p0) = COPY %x0
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[FP:%[0-9]+]](s32) = G_LOAD [[FPADDR]](p0)
|
|
|
|
; CHECK: [[RES:%[0-9]+]](s64) = G_FPTOSI [[FP]](s32)
|
2016-08-20 04:09:11 +08:00
|
|
|
; CHECK: %x0 = COPY [[RES]]
|
|
|
|
define i64 @test_fptosi(float* %fp.addr) {
|
|
|
|
%fp = load float, float* %fp.addr
|
|
|
|
%res = fptosi float %fp to i64
|
|
|
|
ret i64 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_fptoui
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[FPADDR:%[0-9]+]](p0) = COPY %x0
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[FP:%[0-9]+]](s32) = G_LOAD [[FPADDR]](p0)
|
|
|
|
; CHECK: [[RES:%[0-9]+]](s64) = G_FPTOUI [[FP]](s32)
|
2016-08-20 04:09:11 +08:00
|
|
|
; CHECK: %x0 = COPY [[RES]]
|
|
|
|
define i64 @test_fptoui(float* %fp.addr) {
|
|
|
|
%fp = load float, float* %fp.addr
|
|
|
|
%res = fptoui float %fp to i64
|
|
|
|
ret i64 %res
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_sitofp
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x0
|
|
|
|
; CHECK: [[IN:%[0-9]+]](s32) = COPY %w1
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[FP:%[0-9]+]](s64) = G_SITOFP [[IN]](s32)
|
|
|
|
; CHECK: G_STORE [[FP]](s64), [[ADDR]](p0)
|
2016-08-20 04:09:11 +08:00
|
|
|
define void @test_sitofp(double* %addr, i32 %in) {
|
|
|
|
%fp = sitofp i32 %in to double
|
|
|
|
store double %fp, double* %addr
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_uitofp
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x0
|
|
|
|
; CHECK: [[IN:%[0-9]+]](s32) = COPY %w1
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[FP:%[0-9]+]](s64) = G_UITOFP [[IN]](s32)
|
|
|
|
; CHECK: G_STORE [[FP]](s64), [[ADDR]](p0)
|
2016-08-20 04:09:11 +08:00
|
|
|
define void @test_uitofp(double* %addr, i32 %in) {
|
|
|
|
%fp = uitofp i32 %in to double
|
|
|
|
store double %fp, double* %addr
|
|
|
|
ret void
|
|
|
|
}
|
2016-08-20 04:09:15 +08:00
|
|
|
|
2016-08-20 04:48:23 +08:00
|
|
|
; CHECK-LABEL: name: test_fpext
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[IN:%[0-9]+]](s32) = COPY %s0
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[RES:%[0-9]+]](s64) = G_FPEXT [[IN]](s32)
|
2016-08-20 04:48:23 +08:00
|
|
|
; CHECK: %d0 = COPY [[RES]]
|
|
|
|
define double @test_fpext(float %in) {
|
|
|
|
%res = fpext float %in to double
|
|
|
|
ret double %res
|
|
|
|
}
|
|
|
|
|
|
|
|
; CHECK-LABEL: name: test_fptrunc
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[IN:%[0-9]+]](s64) = COPY %d0
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[RES:%[0-9]+]](s32) = G_FPTRUNC [[IN]](s64)
|
2016-08-20 04:48:23 +08:00
|
|
|
; CHECK: %s0 = COPY [[RES]]
|
|
|
|
define float @test_fptrunc(double %in) {
|
|
|
|
%res = fptrunc double %in to float
|
|
|
|
ret float %res
|
|
|
|
}
|
|
|
|
|
2016-08-20 04:09:15 +08:00
|
|
|
; CHECK-LABEL: name: test_constant_float
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x0
|
|
|
|
; CHECK: [[TMP:%[0-9]+]](s32) = G_FCONSTANT float 1.500000e+00
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: G_STORE [[TMP]](s32), [[ADDR]](p0)
|
2016-08-20 04:09:15 +08:00
|
|
|
define void @test_constant_float(float* %addr) {
|
|
|
|
store float 1.5, float* %addr
|
|
|
|
ret void
|
|
|
|
}
|
2016-08-20 04:48:16 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: name: float_comparison
|
2016-09-09 19:46:34 +08:00
|
|
|
; CHECK: [[LHSADDR:%[0-9]+]](p0) = COPY %x0
|
|
|
|
; CHECK: [[RHSADDR:%[0-9]+]](p0) = COPY %x1
|
|
|
|
; CHECK: [[BOOLADDR:%[0-9]+]](p0) = COPY %x2
|
2016-09-12 19:20:10 +08:00
|
|
|
; CHECK: [[LHS:%[0-9]+]](s32) = G_LOAD [[LHSADDR]](p0)
|
|
|
|
; CHECK: [[RHS:%[0-9]+]](s32) = G_LOAD [[RHSADDR]](p0)
|
|
|
|
; CHECK: [[TST:%[0-9]+]](s1) = G_FCMP floatpred(oge), [[LHS]](s32), [[RHS]]
|
|
|
|
; CHECK: G_STORE [[TST]](s1), [[BOOLADDR]](p0)
|
2016-08-20 04:48:16 +08:00
|
|
|
define void @float_comparison(float* %a.addr, float* %b.addr, i1* %bool.addr) {
|
|
|
|
%a = load float, float* %a.addr
|
|
|
|
%b = load float, float* %b.addr
|
|
|
|
%res = fcmp oge float %a, %b
|
|
|
|
store i1 %res, i1* %bool.addr
|
|
|
|
ret void
|
|
|
|
}
|
2016-09-12 20:10:41 +08:00
|
|
|
|
|
|
|
@var = global i32 0
|
|
|
|
|
|
|
|
define i32* @test_global() {
|
|
|
|
; CHECK-LABEL: name: test_global
|
|
|
|
; CHECK: [[TMP:%[0-9]+]](p0) = G_GLOBAL_VALUE @var{{$}}
|
|
|
|
; CHECK: %x0 = COPY [[TMP]](p0)
|
|
|
|
|
|
|
|
ret i32* @var
|
|
|
|
}
|
|
|
|
|
|
|
|
@var1 = addrspace(42) global i32 0
|
|
|
|
define i32 addrspace(42)* @test_global_addrspace() {
|
|
|
|
; CHECK-LABEL: name: test_global
|
|
|
|
; CHECK: [[TMP:%[0-9]+]](p42) = G_GLOBAL_VALUE @var1{{$}}
|
|
|
|
; CHECK: %x0 = COPY [[TMP]](p42)
|
|
|
|
|
|
|
|
ret i32 addrspace(42)* @var1
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define void()* @test_global_func() {
|
|
|
|
; CHECK-LABEL: name: test_global_func
|
|
|
|
; CHECK: [[TMP:%[0-9]+]](p0) = G_GLOBAL_VALUE @allocai64{{$}}
|
|
|
|
; CHECK: %x0 = COPY [[TMP]](p0)
|
|
|
|
|
|
|
|
ret void()* @allocai64
|
|
|
|
}
|
2016-10-19 04:03:45 +08:00
|
|
|
|
|
|
|
declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i32 %align, i1 %volatile)
|
|
|
|
define void @test_memcpy(i8* %dst, i8* %src, i64 %size) {
|
|
|
|
; CHECK-LABEL: name: test_memcpy
|
|
|
|
; CHECK: [[DST:%[0-9]+]](p0) = COPY %x0
|
|
|
|
; CHECK: [[SRC:%[0-9]+]](p0) = COPY %x1
|
|
|
|
; CHECK: [[SIZE:%[0-9]+]](s64) = COPY %x2
|
|
|
|
; CHECK: %x0 = COPY [[DST]]
|
|
|
|
; CHECK: %x1 = COPY [[SRC]]
|
|
|
|
; CHECK: %x2 = COPY [[SIZE]]
|
|
|
|
; CHECK: BL $memcpy, csr_aarch64_aapcs, implicit-def %lr, implicit %sp, implicit %x0, implicit %x1, implicit %x2
|
|
|
|
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %size, i32 1, i1 0)
|
|
|
|
ret void
|
|
|
|
}
|
2016-10-19 04:03:51 +08:00
|
|
|
|
|
|
|
declare i64 @llvm.objectsize.i64(i8*, i1)
|
|
|
|
declare i32 @llvm.objectsize.i32(i8*, i1)
|
|
|
|
define void @test_objectsize(i8* %addr0, i8* %addr1) {
|
|
|
|
; CHECK-LABEL: name: test_objectsize
|
|
|
|
; CHECK: [[ADDR0:%[0-9]+]](p0) = COPY %x0
|
|
|
|
; CHECK: [[ADDR1:%[0-9]+]](p0) = COPY %x1
|
2016-12-06 05:47:07 +08:00
|
|
|
; CHECK: {{%[0-9]+}}(s64) = G_CONSTANT i64 -1
|
|
|
|
; CHECK: {{%[0-9]+}}(s64) = G_CONSTANT i64 0
|
|
|
|
; CHECK: {{%[0-9]+}}(s32) = G_CONSTANT i32 -1
|
|
|
|
; CHECK: {{%[0-9]+}}(s32) = G_CONSTANT i32 0
|
2016-10-19 04:03:51 +08:00
|
|
|
%size64.0 = call i64 @llvm.objectsize.i64(i8* %addr0, i1 0)
|
|
|
|
%size64.intmin = call i64 @llvm.objectsize.i64(i8* %addr0, i1 1)
|
|
|
|
%size32.0 = call i32 @llvm.objectsize.i32(i8* %addr0, i1 0)
|
|
|
|
%size32.intmin = call i32 @llvm.objectsize.i32(i8* %addr0, i1 1)
|
|
|
|
ret void
|
|
|
|
}
|
2016-12-06 05:54:17 +08:00
|
|
|
|
|
|
|
define void @test_large_const(i128* %addr) {
|
|
|
|
; CHECK-LABEL: name: test_large_const
|
|
|
|
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x0
|
|
|
|
; CHECK: [[VAL:%[0-9]+]](s128) = G_CONSTANT i128 42
|
|
|
|
; CHECK: G_STORE [[VAL]](s128), [[ADDR]](p0)
|
|
|
|
store i128 42, i128* %addr
|
|
|
|
ret void
|
|
|
|
}
|
2016-12-06 06:40:13 +08:00
|
|
|
|
|
|
|
; When there was no formal argument handling (so the first BB was empty) we used
|
|
|
|
; to insert the constants at the end of the block, even if they were encountered
|
|
|
|
; after the block's terminators had been emitted.
|
|
|
|
define i32 @test_const_placement() {
|
|
|
|
; CHECK-LABEL: name: test_const_placement
|
|
|
|
; CHECK: [[VAL:%[0-9]+]](s32) = G_CONSTANT i32 42
|
|
|
|
; CHECK: G_BR
|
|
|
|
|
|
|
|
br label %next
|
|
|
|
|
|
|
|
next:
|
|
|
|
ret i32 42
|
|
|
|
}
|