Skip to content

Commit 3ba4092

Browse files
ritter-x2aarsenm
andauthored
[AMDGPU] Check vector sizes for physical register constraints in inline asm (#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 #101190. --------- Co-authored-by: Matt Arsenault <[email protected]>
1 parent 0cf4cb4 commit 3ba4092

File tree

4 files changed

+298
-19
lines changed

4 files changed

+298
-19
lines changed

llvm/lib/Target/AMDGPU/SIISelLowering.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15510,6 +15510,10 @@ SITargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI_,
1551015510
Failed |= !RegName.consume_back("]");
1551115511
if (!Failed) {
1551215512
uint32_t Width = (End - Idx + 1) * 32;
15513+
// Prohibit constraints for register ranges with a width that does not
15514+
// match the required type.
15515+
if (VT.SimpleTy != MVT::Other && Width != VT.getSizeInBits())
15516+
return std::pair(0U, nullptr);
1551315517
MCRegister Reg = RC->getRegister(Idx);
1551415518
if (SIRegisterInfo::isVGPRClass(RC))
1551515519
RC = TRI->getVGPRClassForBitWidth(Width);
@@ -15523,6 +15527,9 @@ SITargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI_,
1552315527
}
1552415528
}
1552515529
} else {
15530+
// Check for lossy scalar/vector conversions.
15531+
if (VT.isVector() && VT.getSizeInBits() != 32)
15532+
return std::pair(0U, nullptr);
1552615533
bool Failed = RegName.getAsInteger(10, Idx);
1552715534
if (!Failed && Idx < RC->getNumRegs())
1552815535
return std::pair(RC->getRegister(Idx), RC);

llvm/test/CodeGen/AMDGPU/GlobalISel/inline-asm-mismatched-size.ll

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
; RUN: FileCheck -check-prefix=ERR %s < %t
44

55
; ERR: remark: <unknown>:0:0: unable to translate instruction: call: ' %sgpr = call <4 x i32> asm sideeffect "; def $0", "={s[8:12]}"()' (in function: return_type_is_too_big_vector)
6+
; ERR: remark: <unknown>:0:0: unable to translate instruction: call: ' %sgpr = call <4 x i32> asm sideeffect "; def $0", "={s[8:10]}"()' (in function: return_type_is_too_small_vector)
67
; ERR: remark: <unknown>:0:0: unable to translate instruction: call: ' %reg = call i64 asm sideeffect "; def $0", "={v8}"()' (in function: return_type_is_too_big_scalar)
8+
; ERR: remark: <unknown>:0:0: unable to translate instruction: call: ' %reg = call i32 asm sideeffect "; def $0", "={v[8:9]}"()' (in function: return_type_is_too_small_scalar)
79
; ERR: remark: <unknown>:0:0: unable to translate instruction: call: ' %reg = call ptr addrspace(1) asm sideeffect "; def $0", "={v8}"()' (in function: return_type_is_too_big_pointer)
810
; ERR: remark: <unknown>:0:0: unable to translate instruction: call: ' %reg = call ptr addrspace(3) asm sideeffect "; def $0", "={v[8:9]}"()' (in function: return_type_is_too_small_pointer)
911
; ERR: remark: <unknown>:0:0: unable to translate instruction: call: ' call void asm sideeffect "; use $0", "{v[0:9]}"(<8 x i32> %arg)' (in function: use_vector_too_big)
1012
; ERR: remark: <unknown>:0:0: unable to translate instruction: call: ' call void asm sideeffect "; use $0", "{v0}"(i64 %arg)' (in function: use_scalar_too_small)
13+
; ERR: remark: <unknown>:0:0: unable to translate instruction: call: ' call void asm sideeffect "; use $0", "{v[0:1]}"(i32 %arg)' (in function: use_scalar_too_big)
1114
; ERR: remark: <unknown>:0:0: unable to translate instruction: call: ' call void asm sideeffect "; use $0", "{v0}"(ptr addrspace(1) %arg)' (in function: use_pointer_too_small)
1215
; ERR: remark: <unknown>:0:0: unable to translate instruction: call: ' call void asm sideeffect "; use $0", "{v[0:1]}"(ptr addrspace(3) %arg)' (in function: use_pointer_too_big)
1316

@@ -24,18 +27,25 @@ define amdgpu_kernel void @return_type_is_too_big_vector() {
2427
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p4) = COPY $sgpr2_sgpr3
2528
; CHECK-NEXT: {{ $}}
2629
; CHECK-NEXT: bb.1 (%ir-block.0):
27-
; CHECK-NEXT: INLINEASM &"; def $0", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $sgpr8_sgpr9_sgpr10_sgpr11_sgpr12
2830
%sgpr = call <4 x i32> asm sideeffect "; def $0", "={s[8:12]}" ()
2931
call void asm sideeffect "; use $0", "s"(<4 x i32> %sgpr) #0
3032
ret void
3133
}
3234

33-
; FIXME: This is crashing in the DAG
34-
; define amdgpu_kernel void @return_type_is_too_small_vector() {
35-
; %sgpr = call <4 x i32> asm sideeffect "; def $0", "={s[8:10]}" ()
36-
; call void asm sideeffect "; use $0", "s"(<4 x i32> %sgpr) #0
37-
; ret void
38-
; }
35+
; This is broken because it requests 3 32-bit sgprs to handle a 4xi32 result.
36+
define amdgpu_kernel void @return_type_is_too_small_vector() {
37+
; CHECK-LABEL: name: return_type_is_too_small_vector
38+
; CHECK: bb.0:
39+
; CHECK-NEXT: successors: %bb.1(0x80000000)
40+
; CHECK-NEXT: liveins: $sgpr2_sgpr3
41+
; CHECK-NEXT: {{ $}}
42+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p4) = COPY $sgpr2_sgpr3
43+
; CHECK-NEXT: {{ $}}
44+
; CHECK-NEXT: bb.1 (%ir-block.0):
45+
%sgpr = call <4 x i32> asm sideeffect "; def $0", "={s[8:10]}" ()
46+
call void asm sideeffect "; use $0", "s"(<4 x i32> %sgpr) #0
47+
ret void
48+
}
3949

4050
define i64 @return_type_is_too_big_scalar() {
4151
; CHECK-LABEL: name: return_type_is_too_big_scalar
@@ -50,12 +60,10 @@ define i64 @return_type_is_too_big_scalar() {
5060

5161
define i32 @return_type_is_too_small_scalar() {
5262
; CHECK-LABEL: name: return_type_is_too_small_scalar
53-
; CHECK: bb.1 (%ir-block.0):
54-
; CHECK-NEXT: INLINEASM &"; def $0", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $vgpr8_vgpr9
55-
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr8_vgpr9
56-
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64)
57-
; CHECK-NEXT: $vgpr0 = COPY [[TRUNC]](s32)
58-
; CHECK-NEXT: SI_RETURN implicit $vgpr0
63+
; CHECK: bb.0:
64+
; CHECK-NEXT: successors: %bb.1(0x80000000)
65+
; CHECK-NEXT: {{ $}}
66+
; CHECK-NEXT: bb.1 (%ir-block.0):
5967
%reg = call i32 asm sideeffect "; def $0", "={v[8:9]}" ()
6068
ret i32 %reg
6169
}
@@ -77,7 +85,6 @@ define ptr addrspace(3) @return_type_is_too_small_pointer() {
7785
; CHECK-NEXT: successors: %bb.1(0x80000000)
7886
; CHECK-NEXT: {{ $}}
7987
; CHECK-NEXT: bb.1 (%ir-block.0):
80-
; CHECK-NEXT: INLINEASM &"; def $0", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $vgpr8_vgpr9
8188
%reg = call ptr addrspace(3) asm sideeffect "; def $0", "={v[8:9]}" ()
8289
ret ptr addrspace(3) %reg
8390
}
@@ -141,14 +148,13 @@ define void @use_scalar_too_small(i64 %arg) {
141148

142149
define void @use_scalar_too_big(i32 %arg) {
143150
; CHECK-LABEL: name: use_scalar_too_big
144-
; CHECK: bb.1 (%ir-block.0):
151+
; CHECK: bb.0:
152+
; CHECK-NEXT: successors: %bb.1(0x80000000)
145153
; CHECK-NEXT: liveins: $vgpr0
146154
; CHECK-NEXT: {{ $}}
147155
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0
148-
; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[COPY]](s32)
149-
; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[ANYEXT]](s64)
150-
; CHECK-NEXT: INLINEASM &"; use $0", 1 /* sideeffect attdialect */, 9 /* reguse */, $vgpr0_vgpr1
151-
; CHECK-NEXT: SI_RETURN
156+
; CHECK-NEXT: {{ $}}
157+
; CHECK-NEXT: bb.1 (%ir-block.0):
152158
call void asm sideeffect "; use $0", "{v[0:1]}"(i32 %arg)
153159
ret void
154160
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
; RUN: not llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s
2+
3+
; Diagnose register constraints that are not wide enough.
4+
5+
; ERR: error: couldn't allocate output register for constraint '{v[8:15]}'
6+
define <9 x i32> @inline_asm_9xi32_in_8v_def() {
7+
%asm = call <9 x i32> asm sideeffect "; def $0", "={v[8:15]}"()
8+
ret <9 x i32> %asm
9+
}
10+
11+
; ERR: error: couldn't allocate input reg for constraint '{v[8:15]}'
12+
define void @inline_asm_9xi32_in_8v_use(<9 x i32> %val) {
13+
call void asm sideeffect "; use $0", "{v[8:15]}"(<9 x i32> %val)
14+
ret void
15+
}
16+
17+
; ERR: error: couldn't allocate output register for constraint '{s[8:15]}'
18+
define <9 x i32> @inline_asm_9xi32_in_8s_def() {
19+
%asm = call <9 x i32> asm sideeffect "; def $0", "={s[8:15]}"()
20+
ret <9 x i32> %asm
21+
}
22+
23+
24+
; Diagnose register constraints that are too wide.
25+
26+
; ERR: error: couldn't allocate output register for constraint '{v[8:16]}'
27+
define <8 x i32> @inline_asm_8xi32_in_9v_def() {
28+
%asm = call <8 x i32> asm sideeffect "; def $0", "={v[8:16]}"()
29+
ret <8 x i32> %asm
30+
}
31+
32+
; ERR: error: couldn't allocate input reg for constraint '{v[8:16]}'
33+
define void @inline_asm_8xi32_in_9v_use(<8 x i32> %val) {
34+
call void asm sideeffect "; use $0", "{v[8:16]}"(<8 x i32> %val)
35+
ret void
36+
}
37+
38+
; ERR: error: couldn't allocate output register for constraint '{s[8:16]}'
39+
define <8 x i32> @inline_asm_8xi32_in_9s_def() {
40+
%asm = call <8 x i32> asm sideeffect "; def $0", "={s[8:16]}"()
41+
ret <8 x i32> %asm
42+
}
43+
44+
45+
; Diagnose mismatched scalars with register ranges
46+
47+
; ERR: error: couldn't allocate output register for constraint '{s[4:5]}'
48+
define void @inline_asm_scalar_read_too_wide() {
49+
%asm = call i32 asm sideeffect "; def $0 ", "={s[4:5]}"()
50+
ret void
51+
}
52+
53+
; ERR: error: couldn't allocate output register for constraint '{s[4:4]}'
54+
define void @inline_asm_scalar_read_too_narrow() {
55+
%asm = call i64 asm sideeffect "; def $0 ", "={s[4:4]}"()
56+
ret void
57+
}
58+
59+
; Single registers for vector types that are too wide or too narrow should be
60+
; diagnosed.
61+
62+
; ERR: error: couldn't allocate input reg for constraint '{v8}'
63+
define void @inline_asm_4xi32_in_v_use(<4 x i32> %val) {
64+
call void asm sideeffect "; use $0", "{v8}"(<4 x i32> %val)
65+
ret void
66+
}
67+
68+
; ERR: error: couldn't allocate output register for constraint '{v8}'
69+
define <4 x i32> @inline_asm_4xi32_in_v_def() {
70+
%asm = call <4 x i32> asm sideeffect "; def $0", "={v8}"()
71+
ret <4 x i32> %asm
72+
}
73+
74+
; ERR: error: couldn't allocate output register for constraint '{s8}'
75+
define <4 x i32> @inline_asm_4xi32_in_s_def() {
76+
%asm = call <4 x i32> asm sideeffect "; def $0", "={s8}"()
77+
ret <4 x i32> %asm
78+
}
79+
80+
; ERR: error: couldn't allocate input reg for constraint '{v8}'
81+
; ERR: error: couldn't allocate input reg for constraint 'v'
82+
define void @inline_asm_2xi8_in_v_use(<2 x i8> %val) {
83+
call void asm sideeffect "; use $0", "{v8}"(<2 x i8> %val)
84+
call void asm sideeffect "; use $0", "v"(<2 x i8> %val)
85+
ret void
86+
}
87+
88+
; ERR: error: couldn't allocate output register for constraint '{v8}'
89+
; ERR: error: couldn't allocate output register for constraint 'v'
90+
define <2 x i8> @inline_asm_2xi8_in_v_def() {
91+
%phys = call <2 x i8> asm sideeffect "; def $0", "={v8}"()
92+
%virt = call <2 x i8> asm sideeffect "; def $0", "=v"()
93+
%r = and <2 x i8> %phys, %virt
94+
ret <2 x i8> %r
95+
}
96+
97+
; ERR: error: couldn't allocate output register for constraint '{s8}'
98+
; ERR: error: couldn't allocate output register for constraint 's'
99+
define <2 x i8> @inline_asm_2xi8_in_s_def() {
100+
%phys = call <2 x i8> asm sideeffect "; def $0", "={s8}"()
101+
%virt = call <2 x i8> asm sideeffect "; def $0", "=s"()
102+
%r = and <2 x i8> %phys, %virt
103+
ret <2 x i8> %r
104+
}
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 < %s | FileCheck -check-prefix=CHECK %s
3+
4+
; Allow single registers that are too wide for the IR type:
5+
6+
define i16 @inline_asm_i16_in_v_def() {
7+
; CHECK-LABEL: inline_asm_i16_in_v_def:
8+
; CHECK: ; %bb.0:
9+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
10+
; CHECK-NEXT: ;;#ASMSTART
11+
; CHECK-NEXT: ; def v8
12+
; CHECK-NEXT: ;;#ASMEND
13+
; CHECK-NEXT: ;;#ASMSTART
14+
; CHECK-NEXT: ; def v0
15+
; CHECK-NEXT: ;;#ASMEND
16+
; CHECK-NEXT: v_and_b32_e32 v0, v8, v0
17+
; CHECK-NEXT: s_setpc_b64 s[30:31]
18+
%phys = call i16 asm sideeffect "; def $0", "={v8}"()
19+
%virt = call i16 asm sideeffect "; def $0", "=v"()
20+
%r = and i16 %phys, %virt
21+
ret i16 %r
22+
}
23+
24+
define void @inline_asm_i16_in_v_use(i16 %val) {
25+
; CHECK-LABEL: inline_asm_i16_in_v_use:
26+
; CHECK: ; %bb.0:
27+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
28+
; CHECK-NEXT: v_and_b32_e32 v8, 0xffff, v0
29+
; CHECK-NEXT: ;;#ASMSTART
30+
; CHECK-NEXT: ; use v8
31+
; CHECK-NEXT: ;;#ASMEND
32+
; CHECK-NEXT: ;;#ASMSTART
33+
; CHECK-NEXT: ; use v8
34+
; CHECK-NEXT: ;;#ASMEND
35+
; CHECK-NEXT: s_setpc_b64 s[30:31]
36+
call void asm sideeffect "; use $0", "{v8}"(i16 %val)
37+
call void asm sideeffect "; use $0", "v"(i16 %val)
38+
ret void
39+
}
40+
41+
define i16 @inline_asm_i16_in_s_def() {
42+
; CHECK-LABEL: inline_asm_i16_in_s_def:
43+
; CHECK: ; %bb.0:
44+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
45+
; CHECK-NEXT: ;;#ASMSTART
46+
; CHECK-NEXT: ; def s8
47+
; CHECK-NEXT: ;;#ASMEND
48+
; CHECK-NEXT: ;;#ASMSTART
49+
; CHECK-NEXT: ; def s4
50+
; CHECK-NEXT: ;;#ASMEND
51+
; CHECK-NEXT: s_and_b32 s4, s8, s4
52+
; CHECK-NEXT: v_mov_b32_e32 v0, s4
53+
; CHECK-NEXT: s_setpc_b64 s[30:31]
54+
%phys = call i16 asm sideeffect "; def $0", "={s8}"()
55+
%virt = call i16 asm sideeffect "; def $0", "=s"()
56+
%r = and i16 %phys, %virt
57+
ret i16 %r
58+
}
59+
60+
define i8 @inline_asm_i8_in_v_def() {
61+
; CHECK-LABEL: inline_asm_i8_in_v_def:
62+
; CHECK: ; %bb.0:
63+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
64+
; CHECK-NEXT: ;;#ASMSTART
65+
; CHECK-NEXT: ; def v8
66+
; CHECK-NEXT: ;;#ASMEND
67+
; CHECK-NEXT: v_mov_b32_e32 v0, v8
68+
; CHECK-NEXT: s_setpc_b64 s[30:31]
69+
%phys = call i8 asm sideeffect "; def $0", "={v8}"()
70+
; %virt = call i8 asm sideeffect "; def $0", "=v"() ; currently fails
71+
; %r = and i8 %phys, %virt
72+
; ret i8 %r
73+
ret i8 %phys
74+
}
75+
76+
; currently broken, v8 should be set to v0 & 0xFF
77+
define void @inline_asm_i8_in_v_use(i8 %val) {
78+
; CHECK-LABEL: inline_asm_i8_in_v_use:
79+
; CHECK: ; %bb.0:
80+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
81+
; CHECK-NEXT: v_mov_b32_e32 v8, v0
82+
; CHECK-NEXT: ;;#ASMSTART
83+
; CHECK-NEXT: ; use v8
84+
; CHECK-NEXT: ;;#ASMEND
85+
; CHECK-NEXT: s_setpc_b64 s[30:31]
86+
call void asm sideeffect "; use $0", "{v8}"(i8 %val)
87+
; call void asm sideeffect "; use $0", "v"(i8 %val) ; currently fails
88+
ret void
89+
}
90+
91+
define i8 @inline_asm_i8_in_sphys_def() {
92+
; CHECK-LABEL: inline_asm_i8_in_sphys_def:
93+
; CHECK: ; %bb.0:
94+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
95+
; CHECK-NEXT: ;;#ASMSTART
96+
; CHECK-NEXT: ; def s8
97+
; CHECK-NEXT: ;;#ASMEND
98+
; CHECK-NEXT: v_mov_b32_e32 v0, s8
99+
; CHECK-NEXT: s_setpc_b64 s[30:31]
100+
%phys = call i8 asm sideeffect "; def $0", "={s8}"()
101+
; %virt = call i8 asm sideeffect "; def $0", "=s"() ; currently fails
102+
; %r = and i8 %phys, %virt
103+
; ret i8 %r
104+
ret i8 %phys
105+
}
106+
107+
108+
; Single registers for vector types that fit are fine.
109+
110+
define void @inline_asm_2xi16_in_v_use(<2 x i16> %val) {
111+
; CHECK-LABEL: inline_asm_2xi16_in_v_use:
112+
; CHECK: ; %bb.0:
113+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
114+
; CHECK-NEXT: v_mov_b32_e32 v8, v0
115+
; CHECK-NEXT: ;;#ASMSTART
116+
; CHECK-NEXT: ; use v8
117+
; CHECK-NEXT: ;;#ASMEND
118+
; CHECK-NEXT: ;;#ASMSTART
119+
; CHECK-NEXT: ; use v0
120+
; CHECK-NEXT: ;;#ASMEND
121+
; CHECK-NEXT: s_setpc_b64 s[30:31]
122+
call void asm sideeffect "; use $0", "{v8}"(<2 x i16> %val)
123+
call void asm sideeffect "; use $0", "v"(<2 x i16> %val)
124+
ret void
125+
}
126+
127+
define <2 x i16> @inline_asm_2xi16_in_v_def() {
128+
; CHECK-LABEL: inline_asm_2xi16_in_v_def:
129+
; CHECK: ; %bb.0:
130+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
131+
; CHECK-NEXT: ;;#ASMSTART
132+
; CHECK-NEXT: ; def v8
133+
; CHECK-NEXT: ;;#ASMEND
134+
; CHECK-NEXT: ;;#ASMSTART
135+
; CHECK-NEXT: ; def v0
136+
; CHECK-NEXT: ;;#ASMEND
137+
; CHECK-NEXT: v_and_b32_e32 v0, v8, v0
138+
; CHECK-NEXT: s_setpc_b64 s[30:31]
139+
%phys = call <2 x i16> asm sideeffect "; def $0", "={v8}"()
140+
%virt = call <2 x i16> asm sideeffect "; def $0", "=v"()
141+
%r = and <2 x i16> %phys, %virt
142+
ret <2 x i16> %r
143+
}
144+
145+
define <2 x i16> @inline_asm_2xi16_in_s_def() {
146+
; CHECK-LABEL: inline_asm_2xi16_in_s_def:
147+
; CHECK: ; %bb.0:
148+
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
149+
; CHECK-NEXT: ;;#ASMSTART
150+
; CHECK-NEXT: ; def s8
151+
; CHECK-NEXT: ;;#ASMEND
152+
; CHECK-NEXT: ;;#ASMSTART
153+
; CHECK-NEXT: ; def s4
154+
; CHECK-NEXT: ;;#ASMEND
155+
; CHECK-NEXT: s_and_b32 s4, s8, s4
156+
; CHECK-NEXT: v_mov_b32_e32 v0, s4
157+
; CHECK-NEXT: s_setpc_b64 s[30:31]
158+
%phys = call <2 x i16> asm sideeffect "; def $0", "={s8}"()
159+
%virt = call <2 x i16> asm sideeffect "; def $0", "=s"()
160+
%r = and <2 x i16> %phys, %virt
161+
ret <2 x i16> %r
162+
}

0 commit comments

Comments
 (0)