[llvm] 1983acc - [SelDAGBuilder] Do not require simple VTs for constraints.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 19 01:41:07 PST 2020


Author: Florian Hahn
Date: 2020-11-19T09:31:54Z
New Revision: 1983acce7c4da01d8fb33b3b3465619f973edd49

URL: https://github.com/llvm/llvm-project/commit/1983acce7c4da01d8fb33b3b3465619f973edd49
DIFF: https://github.com/llvm/llvm-project/commit/1983acce7c4da01d8fb33b3b3465619f973edd49.diff

LOG: [SelDAGBuilder] Do not require simple VTs for constraints.

In some cases, the values passed to `asm sideeffect` calls cannot be
mapped directly to simple MVTs. Currently, we crash in the backend if
that happens. An example can be found in the @test_vector_too_large_r_m
test case, where we pass <9 x float> vectors. In practice, this can
happen in cases like the simple C example below.

using vec = float __attribute__((ext_vector_type(9)));
void f1 (vec m) {
  asm volatile("" : "+r,m"(m) : : "memory");
}

One case that use "+r,m" constraints for arbitrary data types in
practice is google-benchmark's DoNotOptimize.

This patch updates visitInlineAsm so that it use MVT::Other for
constraints with complex VTs. It looks like the rest of the backend
correctly deals with that and properly legalizes the type.

And we still report an error if there are no registers to satisfy the
constraint.

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D91710

Added: 
    

Modified: 
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
    llvm/test/CodeGen/AArch64/arm64-inline-asm.ll
    llvm/test/CodeGen/AArch64/inlineasm-illegal-type.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 278d7b988545..24975e23f3b4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -8087,10 +8087,9 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call) {
         OpInfo.CallOperand = getValue(OpInfo.CallOperandVal);
       }
 
-      OpInfo.ConstraintVT =
-          OpInfo
-              .getCallOperandValEVT(*DAG.getContext(), TLI, DAG.getDataLayout())
-              .getSimpleVT();
+      EVT VT = OpInfo.getCallOperandValEVT(*DAG.getContext(), TLI,
+                                           DAG.getDataLayout());
+      OpInfo.ConstraintVT = VT.isSimple() ? VT.getSimpleVT() : MVT::Other;
     } else if (OpInfo.Type == InlineAsm::isOutput && !OpInfo.isIndirect) {
       // The return value of the call is this value.  As such, there is no
       // corresponding argument.

diff  --git a/llvm/test/CodeGen/AArch64/arm64-inline-asm.ll b/llvm/test/CodeGen/AArch64/arm64-inline-asm.ll
index 3b8b4d848730..5381e65015df 100644
--- a/llvm/test/CodeGen/AArch64/arm64-inline-asm.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-inline-asm.ll
@@ -282,3 +282,18 @@ define void @test_no_hash_in_lane_specifier() {
   tail call void asm sideeffect "fmla v2.4s, v0.4s, v1.s[$0]", "I"(i32 1) #1
   ret void
 }
+define void @test_vector_too_large_r_m(<9 x float>* nocapture readonly %0) {
+; CHECK-LABEL: test_vector_too_large_r_m
+; CHECK:      ldr [[S:s[0-9]+]], [x0, #32]
+; CHECK-DAG:  ldp [[Q0:q[0-9]+]], [[Q1:q[0-9]+]], [x0]
+; CHECK:      str [[S]], [sp, #32]
+; CHECK-DAG   stp [[Q0]], [[Q1]], [sp]
+; CHECK:     ; InlineAsm Start
+;
+entry:
+  %m.addr = alloca <9 x float>, align 16
+  %m = load <9 x float>, <9 x float>* %0, align 16
+  store <9 x float> %m, <9 x float>* %m.addr, align 16
+  call void asm sideeffect "", "=*r|m,0,~{memory}"(<9 x float>* nonnull %m.addr, <9 x float> %m)
+  ret void
+}

diff  --git a/llvm/test/CodeGen/AArch64/inlineasm-illegal-type.ll b/llvm/test/CodeGen/AArch64/inlineasm-illegal-type.ll
index 3fd894cc7e8e..18d6c18979bc 100644
--- a/llvm/test/CodeGen/AArch64/inlineasm-illegal-type.ll
+++ b/llvm/test/CodeGen/AArch64/inlineasm-illegal-type.ll
@@ -2,6 +2,8 @@
 
 ; CHECK: error: couldn't allocate output register for constraint '{d0}'
 ; CHECK: error: couldn't allocate output register for constraint 'w'
+; CHECK: error: couldn't allocate input reg for constraint 'w'
+; CHECK: error: couldn't allocate input reg for constraint 'w'
 
 define hidden double @test1(double %xx) local_unnamed_addr #0 {
 entry:
@@ -15,3 +17,16 @@ entry:
   ret double %0
 }
 
+define void @test_vector_too_large(<8 x float>* nocapture readonly %0) {
+entry:
+  %m = load <8 x float>, <8 x float>* %0, align 16
+  tail call void asm sideeffect "fadd.4s v4, v4, $0", "w,~{memory}"(<8 x float> %m)
+  ret void
+}
+
+define void @test_vector_no_mvt(<9 x float>* nocapture readonly %0) {
+entry:
+  %m = load <9 x float>, <9 x float>* %0, align 16
+  tail call void asm sideeffect "fadd.4s v4, v4, $0", "w,~{memory}"(<9 x float> %m)
+  ret void
+}


        


More information about the llvm-commits mailing list