forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[AMDGPU] Check vector sizes for physical register constraints in inli…
…ne asm (llvm#109955) For register constraints that require specific register ranges, the width of the range should match the type of the associated parameter/return value. With this PR, we error out when that is not the case. Previously, these cases would hit assertions or llvm_unreachables. The handling of register constraints that require only a single register remains more lenient to allow narrower non-vector types for the associated IR values. For example, constraining an i16 or i8 value to a 32-bit register is still allowed. Fixes llvm#101190. --------- Co-authored-by: Matt Arsenault <arsenm2@gmail.com>
- Loading branch information
1 parent
0cf4cb4
commit 3ba4092
Showing
4 changed files
with
298 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 104 additions & 0 deletions
104
llvm/test/CodeGen/AMDGPU/inlineasm-mismatched-size-error.ll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
; RUN: not llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s | ||
|
||
; Diagnose register constraints that are not wide enough. | ||
|
||
; ERR: error: couldn't allocate output register for constraint '{v[8:15]}' | ||
define <9 x i32> @inline_asm_9xi32_in_8v_def() { | ||
%asm = call <9 x i32> asm sideeffect "; def $0", "={v[8:15]}"() | ||
ret <9 x i32> %asm | ||
} | ||
|
||
; ERR: error: couldn't allocate input reg for constraint '{v[8:15]}' | ||
define void @inline_asm_9xi32_in_8v_use(<9 x i32> %val) { | ||
call void asm sideeffect "; use $0", "{v[8:15]}"(<9 x i32> %val) | ||
ret void | ||
} | ||
|
||
; ERR: error: couldn't allocate output register for constraint '{s[8:15]}' | ||
define <9 x i32> @inline_asm_9xi32_in_8s_def() { | ||
%asm = call <9 x i32> asm sideeffect "; def $0", "={s[8:15]}"() | ||
ret <9 x i32> %asm | ||
} | ||
|
||
|
||
; Diagnose register constraints that are too wide. | ||
|
||
; ERR: error: couldn't allocate output register for constraint '{v[8:16]}' | ||
define <8 x i32> @inline_asm_8xi32_in_9v_def() { | ||
%asm = call <8 x i32> asm sideeffect "; def $0", "={v[8:16]}"() | ||
ret <8 x i32> %asm | ||
} | ||
|
||
; ERR: error: couldn't allocate input reg for constraint '{v[8:16]}' | ||
define void @inline_asm_8xi32_in_9v_use(<8 x i32> %val) { | ||
call void asm sideeffect "; use $0", "{v[8:16]}"(<8 x i32> %val) | ||
ret void | ||
} | ||
|
||
; ERR: error: couldn't allocate output register for constraint '{s[8:16]}' | ||
define <8 x i32> @inline_asm_8xi32_in_9s_def() { | ||
%asm = call <8 x i32> asm sideeffect "; def $0", "={s[8:16]}"() | ||
ret <8 x i32> %asm | ||
} | ||
|
||
|
||
; Diagnose mismatched scalars with register ranges | ||
|
||
; ERR: error: couldn't allocate output register for constraint '{s[4:5]}' | ||
define void @inline_asm_scalar_read_too_wide() { | ||
%asm = call i32 asm sideeffect "; def $0 ", "={s[4:5]}"() | ||
ret void | ||
} | ||
|
||
; ERR: error: couldn't allocate output register for constraint '{s[4:4]}' | ||
define void @inline_asm_scalar_read_too_narrow() { | ||
%asm = call i64 asm sideeffect "; def $0 ", "={s[4:4]}"() | ||
ret void | ||
} | ||
|
||
; Single registers for vector types that are too wide or too narrow should be | ||
; diagnosed. | ||
|
||
; ERR: error: couldn't allocate input reg for constraint '{v8}' | ||
define void @inline_asm_4xi32_in_v_use(<4 x i32> %val) { | ||
call void asm sideeffect "; use $0", "{v8}"(<4 x i32> %val) | ||
ret void | ||
} | ||
|
||
; ERR: error: couldn't allocate output register for constraint '{v8}' | ||
define <4 x i32> @inline_asm_4xi32_in_v_def() { | ||
%asm = call <4 x i32> asm sideeffect "; def $0", "={v8}"() | ||
ret <4 x i32> %asm | ||
} | ||
|
||
; ERR: error: couldn't allocate output register for constraint '{s8}' | ||
define <4 x i32> @inline_asm_4xi32_in_s_def() { | ||
%asm = call <4 x i32> asm sideeffect "; def $0", "={s8}"() | ||
ret <4 x i32> %asm | ||
} | ||
|
||
; ERR: error: couldn't allocate input reg for constraint '{v8}' | ||
; ERR: error: couldn't allocate input reg for constraint 'v' | ||
define void @inline_asm_2xi8_in_v_use(<2 x i8> %val) { | ||
call void asm sideeffect "; use $0", "{v8}"(<2 x i8> %val) | ||
call void asm sideeffect "; use $0", "v"(<2 x i8> %val) | ||
ret void | ||
} | ||
|
||
; ERR: error: couldn't allocate output register for constraint '{v8}' | ||
; ERR: error: couldn't allocate output register for constraint 'v' | ||
define <2 x i8> @inline_asm_2xi8_in_v_def() { | ||
%phys = call <2 x i8> asm sideeffect "; def $0", "={v8}"() | ||
%virt = call <2 x i8> asm sideeffect "; def $0", "=v"() | ||
%r = and <2 x i8> %phys, %virt | ||
ret <2 x i8> %r | ||
} | ||
|
||
; ERR: error: couldn't allocate output register for constraint '{s8}' | ||
; ERR: error: couldn't allocate output register for constraint 's' | ||
define <2 x i8> @inline_asm_2xi8_in_s_def() { | ||
%phys = call <2 x i8> asm sideeffect "; def $0", "={s8}"() | ||
%virt = call <2 x i8> asm sideeffect "; def $0", "=s"() | ||
%r = and <2 x i8> %phys, %virt | ||
ret <2 x i8> %r | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 | ||
; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 < %s | FileCheck -check-prefix=CHECK %s | ||
|
||
; Allow single registers that are too wide for the IR type: | ||
|
||
define i16 @inline_asm_i16_in_v_def() { | ||
; CHECK-LABEL: inline_asm_i16_in_v_def: | ||
; CHECK: ; %bb.0: | ||
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) | ||
; CHECK-NEXT: ;;#ASMSTART | ||
; CHECK-NEXT: ; def v8 | ||
; CHECK-NEXT: ;;#ASMEND | ||
; CHECK-NEXT: ;;#ASMSTART | ||
; CHECK-NEXT: ; def v0 | ||
; CHECK-NEXT: ;;#ASMEND | ||
; CHECK-NEXT: v_and_b32_e32 v0, v8, v0 | ||
; CHECK-NEXT: s_setpc_b64 s[30:31] | ||
%phys = call i16 asm sideeffect "; def $0", "={v8}"() | ||
%virt = call i16 asm sideeffect "; def $0", "=v"() | ||
%r = and i16 %phys, %virt | ||
ret i16 %r | ||
} | ||
|
||
define void @inline_asm_i16_in_v_use(i16 %val) { | ||
; CHECK-LABEL: inline_asm_i16_in_v_use: | ||
; CHECK: ; %bb.0: | ||
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) | ||
; CHECK-NEXT: v_and_b32_e32 v8, 0xffff, v0 | ||
; CHECK-NEXT: ;;#ASMSTART | ||
; CHECK-NEXT: ; use v8 | ||
; CHECK-NEXT: ;;#ASMEND | ||
; CHECK-NEXT: ;;#ASMSTART | ||
; CHECK-NEXT: ; use v8 | ||
; CHECK-NEXT: ;;#ASMEND | ||
; CHECK-NEXT: s_setpc_b64 s[30:31] | ||
call void asm sideeffect "; use $0", "{v8}"(i16 %val) | ||
call void asm sideeffect "; use $0", "v"(i16 %val) | ||
ret void | ||
} | ||
|
||
define i16 @inline_asm_i16_in_s_def() { | ||
; CHECK-LABEL: inline_asm_i16_in_s_def: | ||
; CHECK: ; %bb.0: | ||
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) | ||
; CHECK-NEXT: ;;#ASMSTART | ||
; CHECK-NEXT: ; def s8 | ||
; CHECK-NEXT: ;;#ASMEND | ||
; CHECK-NEXT: ;;#ASMSTART | ||
; CHECK-NEXT: ; def s4 | ||
; CHECK-NEXT: ;;#ASMEND | ||
; CHECK-NEXT: s_and_b32 s4, s8, s4 | ||
; CHECK-NEXT: v_mov_b32_e32 v0, s4 | ||
; CHECK-NEXT: s_setpc_b64 s[30:31] | ||
%phys = call i16 asm sideeffect "; def $0", "={s8}"() | ||
%virt = call i16 asm sideeffect "; def $0", "=s"() | ||
%r = and i16 %phys, %virt | ||
ret i16 %r | ||
} | ||
|
||
define i8 @inline_asm_i8_in_v_def() { | ||
; CHECK-LABEL: inline_asm_i8_in_v_def: | ||
; CHECK: ; %bb.0: | ||
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) | ||
; CHECK-NEXT: ;;#ASMSTART | ||
; CHECK-NEXT: ; def v8 | ||
; CHECK-NEXT: ;;#ASMEND | ||
; CHECK-NEXT: v_mov_b32_e32 v0, v8 | ||
; CHECK-NEXT: s_setpc_b64 s[30:31] | ||
%phys = call i8 asm sideeffect "; def $0", "={v8}"() | ||
; %virt = call i8 asm sideeffect "; def $0", "=v"() ; currently fails | ||
; %r = and i8 %phys, %virt | ||
; ret i8 %r | ||
ret i8 %phys | ||
} | ||
|
||
; currently broken, v8 should be set to v0 & 0xFF | ||
define void @inline_asm_i8_in_v_use(i8 %val) { | ||
; CHECK-LABEL: inline_asm_i8_in_v_use: | ||
; CHECK: ; %bb.0: | ||
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) | ||
; CHECK-NEXT: v_mov_b32_e32 v8, v0 | ||
; CHECK-NEXT: ;;#ASMSTART | ||
; CHECK-NEXT: ; use v8 | ||
; CHECK-NEXT: ;;#ASMEND | ||
; CHECK-NEXT: s_setpc_b64 s[30:31] | ||
call void asm sideeffect "; use $0", "{v8}"(i8 %val) | ||
; call void asm sideeffect "; use $0", "v"(i8 %val) ; currently fails | ||
ret void | ||
} | ||
|
||
define i8 @inline_asm_i8_in_sphys_def() { | ||
; CHECK-LABEL: inline_asm_i8_in_sphys_def: | ||
; CHECK: ; %bb.0: | ||
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) | ||
; CHECK-NEXT: ;;#ASMSTART | ||
; CHECK-NEXT: ; def s8 | ||
; CHECK-NEXT: ;;#ASMEND | ||
; CHECK-NEXT: v_mov_b32_e32 v0, s8 | ||
; CHECK-NEXT: s_setpc_b64 s[30:31] | ||
%phys = call i8 asm sideeffect "; def $0", "={s8}"() | ||
; %virt = call i8 asm sideeffect "; def $0", "=s"() ; currently fails | ||
; %r = and i8 %phys, %virt | ||
; ret i8 %r | ||
ret i8 %phys | ||
} | ||
|
||
|
||
; Single registers for vector types that fit are fine. | ||
|
||
define void @inline_asm_2xi16_in_v_use(<2 x i16> %val) { | ||
; CHECK-LABEL: inline_asm_2xi16_in_v_use: | ||
; CHECK: ; %bb.0: | ||
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) | ||
; CHECK-NEXT: v_mov_b32_e32 v8, v0 | ||
; CHECK-NEXT: ;;#ASMSTART | ||
; CHECK-NEXT: ; use v8 | ||
; CHECK-NEXT: ;;#ASMEND | ||
; CHECK-NEXT: ;;#ASMSTART | ||
; CHECK-NEXT: ; use v0 | ||
; CHECK-NEXT: ;;#ASMEND | ||
; CHECK-NEXT: s_setpc_b64 s[30:31] | ||
call void asm sideeffect "; use $0", "{v8}"(<2 x i16> %val) | ||
call void asm sideeffect "; use $0", "v"(<2 x i16> %val) | ||
ret void | ||
} | ||
|
||
define <2 x i16> @inline_asm_2xi16_in_v_def() { | ||
; CHECK-LABEL: inline_asm_2xi16_in_v_def: | ||
; CHECK: ; %bb.0: | ||
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) | ||
; CHECK-NEXT: ;;#ASMSTART | ||
; CHECK-NEXT: ; def v8 | ||
; CHECK-NEXT: ;;#ASMEND | ||
; CHECK-NEXT: ;;#ASMSTART | ||
; CHECK-NEXT: ; def v0 | ||
; CHECK-NEXT: ;;#ASMEND | ||
; CHECK-NEXT: v_and_b32_e32 v0, v8, v0 | ||
; CHECK-NEXT: s_setpc_b64 s[30:31] | ||
%phys = call <2 x i16> asm sideeffect "; def $0", "={v8}"() | ||
%virt = call <2 x i16> asm sideeffect "; def $0", "=v"() | ||
%r = and <2 x i16> %phys, %virt | ||
ret <2 x i16> %r | ||
} | ||
|
||
define <2 x i16> @inline_asm_2xi16_in_s_def() { | ||
; CHECK-LABEL: inline_asm_2xi16_in_s_def: | ||
; CHECK: ; %bb.0: | ||
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) | ||
; CHECK-NEXT: ;;#ASMSTART | ||
; CHECK-NEXT: ; def s8 | ||
; CHECK-NEXT: ;;#ASMEND | ||
; CHECK-NEXT: ;;#ASMSTART | ||
; CHECK-NEXT: ; def s4 | ||
; CHECK-NEXT: ;;#ASMEND | ||
; CHECK-NEXT: s_and_b32 s4, s8, s4 | ||
; CHECK-NEXT: v_mov_b32_e32 v0, s4 | ||
; CHECK-NEXT: s_setpc_b64 s[30:31] | ||
%phys = call <2 x i16> asm sideeffect "; def $0", "={s8}"() | ||
%virt = call <2 x i16> asm sideeffect "; def $0", "=s"() | ||
%r = and <2 x i16> %phys, %virt | ||
ret <2 x i16> %r | ||
} |