[PATCH] D87485: [X86] Don't match x87 register inline asm constraints unless the VT is floating point or its a clobber
Craig Topper via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 17 11:27:41 PDT 2020
This revision was automatically updated to reflect the committed changes.
Closed by commit rG3783d3bc7b3d: [X86] Don't match x87 register inline asm constraints unless the VT is floating… (authored by craig.topper).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D87485/new/
https://reviews.llvm.org/D87485
Files:
llvm/lib/Target/X86/X86ISelLowering.cpp
llvm/test/CodeGen/X86/asm-reject-x87-int.ll
Index: llvm/test/CodeGen/X86/asm-reject-x87-int.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/X86/asm-reject-x87-int.ll
@@ -0,0 +1,39 @@
+; RUN: not llc -o /dev/null %s -mtriple=i386-unknown-unknown 2>&1 | FileCheck %s
+
+; This test was derived from this C code. The frontend sees that the constraint
+; doesn't accept memory, but the argument is a strict. So it tries to bitcast
+; to an integer of the same size. SelectionDAGBuilder doesn't know how to copy
+; between integers and fp80 so it asserts or crashes.
+;
+; gcc accepts the code. But rejects it if the struct is replaced by an int. From
+; the InlineAsm block those two cases look the same in LLVM IR. So if the single
+; elementstruct case is valid, then the frontend needs to emit different IR.
+
+; typedef struct float4 {
+; float f;
+; } float4;
+;
+; int main() {
+; float4 f4;
+; f4.f = 4.0f;
+; __asm ("fadd %%st(0), %%st(0)" : "+t" (f4));
+; return 0;
+; }
+
+%struct.float4 = type { float }
+
+; CHECK: error: couldn't allocate output register for constraint '{st}'
+define dso_local i32 @foo() {
+entry:
+ %retval = alloca i32, align 4
+ %f4 = alloca %struct.float4, align 4
+ store i32 0, i32* %retval, align 4
+ %f = getelementptr inbounds %struct.float4, %struct.float4* %f4, i32 0, i32 0
+ store float 4.000000e+00, float* %f, align 4
+ %0 = bitcast %struct.float4* %f4 to i32*
+ %1 = load i32, i32* %0, align 4
+ %2 = call i32 asm "fadd %st(0), %st(0)", "={st},0,~{dirflag},~{fpsr},~{flags}"(i32 %1)
+ %3 = bitcast %struct.float4* %f4 to i32*
+ store i32 %2, i32* %3, align 4
+ ret i32 0
+}
Index: llvm/lib/Target/X86/X86ISelLowering.cpp
===================================================================
--- llvm/lib/Target/X86/X86ISelLowering.cpp
+++ llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -50618,23 +50618,27 @@
// Not found as a standard register?
if (!Res.second) {
- // Map st(0) -> st(7) -> ST0
- if (Constraint.size() == 7 && Constraint[0] == '{' &&
- tolower(Constraint[1]) == 's' && tolower(Constraint[2]) == 't' &&
- Constraint[3] == '(' &&
- (Constraint[4] >= '0' && Constraint[4] <= '7') &&
- Constraint[5] == ')' && Constraint[6] == '}') {
- // st(7) is not allocatable and thus not a member of RFP80. Return
- // singleton class in cases where we have a reference to it.
- if (Constraint[4] == '7')
- return std::make_pair(X86::FP7, &X86::RFP80_7RegClass);
- return std::make_pair(X86::FP0 + Constraint[4] - '0',
- &X86::RFP80RegClass);
- }
-
- // GCC allows "st(0)" to be called just plain "st".
- if (StringRef("{st}").equals_lower(Constraint))
- return std::make_pair(X86::FP0, &X86::RFP80RegClass);
+ // Only match x87 registers if the VT is one SelectionDAGBuilder can convert
+ // to/from f80.
+ if (VT == MVT::Other || VT == MVT::f32 || VT == MVT::f64 || VT == MVT::f80) {
+ // Map st(0) -> st(7) -> ST0
+ if (Constraint.size() == 7 && Constraint[0] == '{' &&
+ tolower(Constraint[1]) == 's' && tolower(Constraint[2]) == 't' &&
+ Constraint[3] == '(' &&
+ (Constraint[4] >= '0' && Constraint[4] <= '7') &&
+ Constraint[5] == ')' && Constraint[6] == '}') {
+ // st(7) is not allocatable and thus not a member of RFP80. Return
+ // singleton class in cases where we have a reference to it.
+ if (Constraint[4] == '7')
+ return std::make_pair(X86::FP7, &X86::RFP80_7RegClass);
+ return std::make_pair(X86::FP0 + Constraint[4] - '0',
+ &X86::RFP80RegClass);
+ }
+
+ // GCC allows "st(0)" to be called just plain "st".
+ if (StringRef("{st}").equals_lower(Constraint))
+ return std::make_pair(X86::FP0, &X86::RFP80RegClass);
+ }
// flags -> EFLAGS
if (StringRef("{flags}").equals_lower(Constraint))
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D87485.292571.patch
Type: text/x-patch
Size: 3952 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200917/2e67bc21/attachment.bin>
More information about the llvm-commits
mailing list