The first trivial example I tried failed to merge due to the user scan logic. Remove the complicated scan of users handling with distance thresholds, with a same block restriction. The actual expansion of sincos is basically the same size as sin or cos individually. Copy the technique the generic optimization uses, which is to just use the input instruction as the insert point or just insert at the start of the entry block. https://reviews.llvm.org/D156706
190 lines
9.0 KiB
LLVM
190 lines
9.0 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
|
|
; RUN: opt -S -mtriple=amdgcn-- -passes=amdgpu-simplifylib < %s | FileCheck %s
|
|
|
|
target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8"
|
|
|
|
; sin, cos, and sincos are already defined in the module.
|
|
|
|
define float @_Z3sinf(float %x) {
|
|
; CHECK-LABEL: define float @_Z3sinf
|
|
; CHECK-SAME: (float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[RESULT:%.*]] = call float asm "
|
|
; CHECK-NEXT: ret float [[RESULT]]
|
|
;
|
|
%result = call float asm "; $0 = sin($1)","=v,v"(float %x)
|
|
ret float %result
|
|
}
|
|
|
|
define float @_Z3cosf(float %x) {
|
|
; CHECK-LABEL: define float @_Z3cosf
|
|
; CHECK-SAME: (float [[X:%.*]]) {
|
|
; CHECK-NEXT: [[RESULT:%.*]] = call float asm "
|
|
; CHECK-NEXT: ret float [[RESULT]]
|
|
;
|
|
%result = call float asm "; $0 = cos($1)","=v,v"(float %x)
|
|
ret float %result
|
|
}
|
|
|
|
define <2 x float> @_Z3sinDv2_f(<2 x float> %x) {
|
|
; CHECK-LABEL: define <2 x float> @_Z3sinDv2_f
|
|
; CHECK-SAME: (<2 x float> [[X:%.*]]) {
|
|
; CHECK-NEXT: [[RESULT:%.*]] = call <2 x float> asm "
|
|
; CHECK-NEXT: ret <2 x float> [[RESULT]]
|
|
;
|
|
%result = call <2 x float> asm "; $0 = sin($1)","=v,v"(<2 x float> %x)
|
|
ret <2 x float> %result
|
|
}
|
|
|
|
define <2 x float> @_Z3cosDv2_f(<2 x float> %x) {
|
|
; CHECK-LABEL: define <2 x float> @_Z3cosDv2_f
|
|
; CHECK-SAME: (<2 x float> [[X:%.*]]) {
|
|
; CHECK-NEXT: [[RESULT:%.*]] = call <2 x float> asm "
|
|
; CHECK-NEXT: ret <2 x float> [[RESULT]]
|
|
;
|
|
%result = call <2 x float> asm "; $0 = cos($1)","=v,v"(<2 x float> %x)
|
|
ret <2 x float> %result
|
|
}
|
|
|
|
define float @_Z6sincosfPU3AS5f(float %x, ptr addrspace(5) %ptr) {
|
|
; CHECK-LABEL: define float @_Z6sincosfPU3AS5f
|
|
; CHECK-SAME: (float [[X:%.*]], ptr addrspace(5) [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[RESULT0:%.*]] = call float asm "
|
|
; CHECK-NEXT: [[RESULT1:%.*]] = call float asm "
|
|
; CHECK-NEXT: store float [[RESULT1]], ptr addrspace(5) [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[RESULT0]]
|
|
;
|
|
%result0 = call float asm "; $0 = sin($1)","=v,v"(float %x)
|
|
%result1 = call float asm "; $0 = cos($1)","=v,v"(float %x)
|
|
store float %result1, ptr addrspace(5) %ptr
|
|
ret float %result0
|
|
}
|
|
|
|
define <2 x float> @_Z6sincosDv2_fPU3AS5S_(<2 x float> %x, ptr addrspace(5) %ptr) {
|
|
; CHECK-LABEL: define <2 x float> @_Z6sincosDv2_fPU3AS5S_
|
|
; CHECK-SAME: (<2 x float> [[X:%.*]], ptr addrspace(5) [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[RESULT0:%.*]] = call <2 x float> asm "
|
|
; CHECK-NEXT: [[RESULT1:%.*]] = call <2 x float> asm "
|
|
; CHECK-NEXT: store <2 x float> [[RESULT1]], ptr addrspace(5) [[PTR]], align 8
|
|
; CHECK-NEXT: ret <2 x float> [[RESULT0]]
|
|
;
|
|
%result0 = call <2 x float> asm "; $0 = sin($1)","=v,v"(<2 x float> %x)
|
|
%result1 = call <2 x float> asm "; $0 = cos($1)","=v,v"(<2 x float> %x)
|
|
store <2 x float> %result1, ptr addrspace(5) %ptr
|
|
ret <2 x float> %result0
|
|
}
|
|
|
|
define float @_Z6sincosfPU3AS0f(float %x, ptr %ptr) {
|
|
; CHECK-LABEL: define float @_Z6sincosfPU3AS0f
|
|
; CHECK-SAME: (float [[X:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[RESULT0:%.*]] = call float asm "
|
|
; CHECK-NEXT: [[RESULT1:%.*]] = call float asm "
|
|
; CHECK-NEXT: store float [[RESULT1]], ptr [[PTR]], align 4
|
|
; CHECK-NEXT: ret float [[RESULT0]]
|
|
;
|
|
%result0 = call float asm "; $0 = sin($1)","=v,v"(float %x)
|
|
%result1 = call float asm "; $0 = cos($1)","=v,v"(float %x)
|
|
store float %result1, ptr %ptr
|
|
ret float %result0
|
|
}
|
|
|
|
define <2 x float> @_Z6sincosDv2_fPU3AS0S_(<2 x float> %x, ptr %ptr) {
|
|
; CHECK-LABEL: define <2 x float> @_Z6sincosDv2_fPU3AS0S_
|
|
; CHECK-SAME: (<2 x float> [[X:%.*]], ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[RESULT0:%.*]] = call <2 x float> asm "
|
|
; CHECK-NEXT: [[RESULT1:%.*]] = call <2 x float> asm "
|
|
; CHECK-NEXT: store <2 x float> [[RESULT1]], ptr [[PTR]], align 8
|
|
; CHECK-NEXT: ret <2 x float> [[RESULT0]]
|
|
;
|
|
%result0 = call <2 x float> asm "; $0 = sin($1)","=v,v"(<2 x float> %x)
|
|
%result1 = call <2 x float> asm "; $0 = cos($1)","=v,v"(<2 x float> %x)
|
|
store <2 x float> %result1, ptr %ptr
|
|
ret <2 x float> %result0
|
|
}
|
|
|
|
define void @sincos_f32(float %x, ptr addrspace(1) nocapture writeonly %sin_out, ptr addrspace(1) nocapture writeonly %cos_out) {
|
|
; CHECK-LABEL: define void @sincos_f32
|
|
; CHECK-SAME: (float [[X:%.*]], ptr addrspace(1) nocapture writeonly [[SIN_OUT:%.*]], ptr addrspace(1) nocapture writeonly [[COS_OUT:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[__SINCOS_:%.*]] = alloca float, align 4, addrspace(5)
|
|
; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr addrspace(5) [[__SINCOS_]] to ptr
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call contract float @_Z6sincosfPU3AS0f(float [[X]], ptr [[TMP0]])
|
|
; CHECK-NEXT: [[TMP2:%.*]] = load float, ptr addrspace(5) [[__SINCOS_]], align 4
|
|
; CHECK-NEXT: store float [[TMP1]], ptr addrspace(1) [[SIN_OUT]], align 4
|
|
; CHECK-NEXT: store float [[TMP2]], ptr addrspace(1) [[COS_OUT]], align 4
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%call = tail call contract float @_Z3sinf(float %x)
|
|
store float %call, ptr addrspace(1) %sin_out, align 4
|
|
%call1 = tail call contract float @_Z3cosf(float %x)
|
|
store float %call1, ptr addrspace(1) %cos_out, align 4
|
|
ret void
|
|
}
|
|
|
|
define void @sincos_f32_value_is_same_constantfp(ptr addrspace(1) nocapture writeonly %sin_out, ptr addrspace(1) nocapture writeonly %cos_out) {
|
|
; CHECK-LABEL: define void @sincos_f32_value_is_same_constantfp
|
|
; CHECK-SAME: (ptr addrspace(1) nocapture writeonly [[SIN_OUT:%.*]], ptr addrspace(1) nocapture writeonly [[COS_OUT:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[__SINCOS_:%.*]] = alloca float, align 4, addrspace(5)
|
|
; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr addrspace(5) [[__SINCOS_]] to ptr
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call contract float @_Z6sincosfPU3AS0f(float 4.200000e+01, ptr [[TMP0]])
|
|
; CHECK-NEXT: [[TMP2:%.*]] = load float, ptr addrspace(5) [[__SINCOS_]], align 4
|
|
; CHECK-NEXT: store float [[TMP1]], ptr addrspace(1) [[SIN_OUT]], align 4
|
|
; CHECK-NEXT: store float [[TMP2]], ptr addrspace(1) [[COS_OUT]], align 4
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%call = tail call contract float @_Z3sinf(float 42.0)
|
|
store float %call, ptr addrspace(1) %sin_out, align 4
|
|
%call1 = tail call contract float @_Z3cosf(float 42.0)
|
|
store float %call1, ptr addrspace(1) %cos_out, align 4
|
|
ret void
|
|
}
|
|
|
|
define void @sincos_v2f32(<2 x float> %x, ptr addrspace(1) nocapture writeonly %sin_out, ptr addrspace(1) nocapture writeonly %cos_out) {
|
|
; GCN-LABEL: define void @sincos_v2f32
|
|
; GCN-SAME: (<2 x float> [[X:%.*]], ptr addrspace(1) nocapture writeonly [[SIN_OUT:%.*]], ptr addrspace(1) nocapture writeonly [[COS_OUT:%.*]]) local_unnamed_addr {
|
|
; GCN-NEXT: entry:
|
|
; GCN-NEXT: [[CALL:%.*]] = tail call contract <2 x float> @_Z3sinDv2_f(<2 x float> [[X]])
|
|
; GCN-NEXT: store <2 x float> [[CALL]], ptr addrspace(1) [[SIN_OUT]], align 8
|
|
; GCN-NEXT: [[CALL1:%.*]] = tail call contract <2 x float> @_Z3cosDv2_f(<2 x float> [[X]])
|
|
; GCN-NEXT: store <2 x float> [[CALL1]], ptr addrspace(1) [[COS_OUT]], align 8
|
|
; GCN-NEXT: ret void
|
|
;
|
|
; CHECK-LABEL: define void @sincos_v2f32
|
|
; CHECK-SAME: (<2 x float> [[X:%.*]], ptr addrspace(1) nocapture writeonly [[SIN_OUT:%.*]], ptr addrspace(1) nocapture writeonly [[COS_OUT:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[__SINCOS_:%.*]] = alloca <2 x float>, align 8, addrspace(5)
|
|
; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr addrspace(5) [[__SINCOS_]] to ptr
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call contract <2 x float> @_Z6sincosDv2_fPU3AS0S_(<2 x float> [[X]], ptr [[TMP0]])
|
|
; CHECK-NEXT: [[TMP2:%.*]] = load <2 x float>, ptr addrspace(5) [[__SINCOS_]], align 8
|
|
; CHECK-NEXT: store <2 x float> [[TMP1]], ptr addrspace(1) [[SIN_OUT]], align 8
|
|
; CHECK-NEXT: store <2 x float> [[TMP2]], ptr addrspace(1) [[COS_OUT]], align 8
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%call = tail call contract <2 x float> @_Z3sinDv2_f(<2 x float> %x)
|
|
store <2 x float> %call, ptr addrspace(1) %sin_out, align 8
|
|
%call1 = tail call contract <2 x float> @_Z3cosDv2_f(<2 x float> %x)
|
|
store <2 x float> %call1, ptr addrspace(1) %cos_out, align 8
|
|
ret void
|
|
}
|
|
|
|
define void @sincos_f32_nobuiltin_callsite(float %x, ptr addrspace(1) nocapture writeonly %sin_out, ptr addrspace(1) nocapture writeonly %cos_out) {
|
|
; CHECK-LABEL: define void @sincos_f32_nobuiltin_callsite
|
|
; CHECK-SAME: (float [[X:%.*]], ptr addrspace(1) nocapture writeonly [[SIN_OUT:%.*]], ptr addrspace(1) nocapture writeonly [[COS_OUT:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call contract float @_Z3sinf(float [[X]]) #[[ATTR0:[0-9]+]]
|
|
; CHECK-NEXT: store float [[CALL]], ptr addrspace(1) [[SIN_OUT]], align 4
|
|
; CHECK-NEXT: [[CALL1:%.*]] = tail call contract float @_Z3cosf(float [[X]]) #[[ATTR0]]
|
|
; CHECK-NEXT: store float [[CALL1]], ptr addrspace(1) [[COS_OUT]], align 4
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%call = tail call contract float @_Z3sinf(float %x) nobuiltin
|
|
store float %call, ptr addrspace(1) %sin_out, align 4
|
|
%call1 = tail call contract float @_Z3cosf(float %x) nobuiltin
|
|
store float %call1, ptr addrspace(1) %cos_out, align 4
|
|
ret void
|
|
}
|