https://github.com/aqjune updated https://github.com/llvm/llvm-project/pull/77281
>From 1bbfe05bc50e1fbdb207f21a178b6fc7ab24e8cf Mon Sep 17 00:00:00 2001 From: Juneyoung Lee <aqj...@gmail.com> Date: Mon, 8 Jan 2024 02:01:41 -0600 Subject: [PATCH 1/3] [WebAssembly] Correctly consider signext/zext arg flags at function declaration --- .../WebAssembly/WebAssemblyFastISel.cpp | 6 +- .../WebAssembly/signext-zeroext-callsite.ll | 125 ++++++++++++++++++ 2 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/WebAssembly/signext-zeroext-callsite.ll diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp index 15dc44a0439573..80159974ecd691 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -839,9 +839,11 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) { unsigned Reg; - if (Attrs.hasParamAttr(I, Attribute::SExt)) + if (Attrs.hasParamAttr(I, Attribute::SExt) || + (IsDirect && Func->hasParamAttribute(I, Attribute::SExt))) Reg = getRegForSignedValue(V); - else if (Attrs.hasParamAttr(I, Attribute::ZExt)) + else if (Attrs.hasParamAttr(I, Attribute::ZExt) || + (IsDirect && Func->hasParamAttribute(I, Attribute::ZExt))) Reg = getRegForUnsignedValue(V); else Reg = getRegForValue(V); diff --git a/llvm/test/CodeGen/WebAssembly/signext-zeroext-callsite.ll b/llvm/test/CodeGen/WebAssembly/signext-zeroext-callsite.ll new file mode 100644 index 00000000000000..02ca578716dc98 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/signext-zeroext-callsite.ll @@ -0,0 +1,125 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -O0 | FileCheck %s + +target triple = "wasm32-unknown-unknown" + + +declare i32 @foo(i1 signext noundef, i32 noundef) + +; callsite_signext and callsite_nosignext must emit equivalent codes + +define i32 @callsite_nosignext() { +; CHECK-LABEL: callsite_nosignext: +; CHECK: .functype callsite_nosignext () -> (i32) +; CHECK-NEXT: .local i32, i32, i32, i32, i32, i32 +; CHECK-NEXT: # %bb.0: # %start +; CHECK-NEXT: i32.const 1 +; CHECK-NEXT: local.set 0 +; CHECK-NEXT: i32.const 0 +; CHECK-NEXT: local.set 1 +; CHECK-NEXT: i32.const 31 +; CHECK-NEXT: local.set 2 +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: local.get 2 +; CHECK-NEXT: i32.shl +; CHECK-NEXT: local.set 3 +; CHECK-NEXT: local.get 3 +; CHECK-NEXT: local.get 2 +; CHECK-NEXT: i32.shr_s +; CHECK-NEXT: local.set 4 +; CHECK-NEXT: local.get 4 +; CHECK-NEXT: local.get 1 +; CHECK-NEXT: call foo +; CHECK-NEXT: local.set 5 +; CHECK-NEXT: local.get 5 +; CHECK-NEXT: return +start: + %0 = call i32 @foo(i1 1, i32 0) + ret i32 %0 +} + +define i32 @callsite_signext() { +; CHECK-LABEL: callsite_signext: +; CHECK: .functype callsite_signext () -> (i32) +; CHECK-NEXT: .local i32, i32, i32, i32, i32, i32 +; CHECK-NEXT: # %bb.0: # %start +; CHECK-NEXT: i32.const 1 +; CHECK-NEXT: local.set 0 +; CHECK-NEXT: i32.const 0 +; CHECK-NEXT: local.set 1 +; CHECK-NEXT: i32.const 31 +; CHECK-NEXT: local.set 2 +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: local.get 2 +; CHECK-NEXT: i32.shl +; CHECK-NEXT: local.set 3 +; CHECK-NEXT: local.get 3 +; CHECK-NEXT: local.get 2 +; CHECK-NEXT: i32.shr_s +; CHECK-NEXT: local.set 4 +; CHECK-NEXT: local.get 4 +; CHECK-NEXT: local.get 1 +; CHECK-NEXT: call foo +; CHECK-NEXT: local.set 5 +; CHECK-NEXT: local.get 5 +; CHECK-NEXT: return +start: + %0 = call i32 @foo(i1 signext 1, i32 0) + ret i32 %0 +} + +declare i32 @foo2(i1 zeroext noundef, i32 noundef) + +; callsite_zeroext and callsite_nozeroext must emit equivalent codes + +define i32 @callsite_nozeroext() { +; CHECK-LABEL: callsite_nozeroext: +; CHECK: .functype callsite_nozeroext () -> (i32) +; CHECK-NEXT: .local i32, i32, i32, i32, i32 +; CHECK-NEXT: # %bb.0: # %start +; CHECK-NEXT: i32.const 1 +; CHECK-NEXT: local.set 0 +; CHECK-NEXT: i32.const 0 +; CHECK-NEXT: local.set 1 +; CHECK-NEXT: i32.const 1 +; CHECK-NEXT: local.set 2 +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: local.get 2 +; CHECK-NEXT: i32.and +; CHECK-NEXT: local.set 3 +; CHECK-NEXT: local.get 3 +; CHECK-NEXT: local.get 1 +; CHECK-NEXT: call foo2 +; CHECK-NEXT: local.set 4 +; CHECK-NEXT: local.get 4 +; CHECK-NEXT: return +start: + %0 = call i32 @foo2(i1 1, i32 0) + ret i32 %0 +} + +define i32 @callsite_zeroext() { +; CHECK-LABEL: callsite_zeroext: +; CHECK: .functype callsite_zeroext () -> (i32) +; CHECK-NEXT: .local i32, i32, i32, i32, i32 +; CHECK-NEXT: # %bb.0: # %start +; CHECK-NEXT: i32.const 1 +; CHECK-NEXT: local.set 0 +; CHECK-NEXT: i32.const 0 +; CHECK-NEXT: local.set 1 +; CHECK-NEXT: i32.const 1 +; CHECK-NEXT: local.set 2 +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: local.get 2 +; CHECK-NEXT: i32.and +; CHECK-NEXT: local.set 3 +; CHECK-NEXT: local.get 3 +; CHECK-NEXT: local.get 1 +; CHECK-NEXT: call foo2 +; CHECK-NEXT: local.set 4 +; CHECK-NEXT: local.get 4 +; CHECK-NEXT: return +start: + %0 = call i32 @foo2(i1 zeroext 1, i32 0) + ret i32 %0 +} >From 3d2eb3187d7b5d995b529e9a5cc3d2496478af4b Mon Sep 17 00:00:00 2001 From: Juneyoung Lee <aqj...@gmail.com> Date: Mon, 8 Jan 2024 17:48:32 -0600 Subject: [PATCH 2/3] add fast-isel=false case --- .../WebAssembly/signext-zeroext-callsite.ll | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/llvm/test/CodeGen/WebAssembly/signext-zeroext-callsite.ll b/llvm/test/CodeGen/WebAssembly/signext-zeroext-callsite.ll index 02ca578716dc98..e33337f2780609 100644 --- a/llvm/test/CodeGen/WebAssembly/signext-zeroext-callsite.ll +++ b/llvm/test/CodeGen/WebAssembly/signext-zeroext-callsite.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -O0 | FileCheck %s +; RUN: llc -fast-isel=false < %s -O0 | FileCheck %s -check-prefixes NO-FAST-ISEL target triple = "wasm32-unknown-unknown" @@ -33,6 +34,21 @@ define i32 @callsite_nosignext() { ; CHECK-NEXT: local.set 5 ; CHECK-NEXT: local.get 5 ; CHECK-NEXT: return +; +; NO-FAST-ISEL-LABEL: callsite_nosignext: +; NO-FAST-ISEL: .functype callsite_nosignext () -> (i32) +; NO-FAST-ISEL-NEXT: .local i32, i32, i32 +; NO-FAST-ISEL-NEXT: # %bb.0: # %start +; NO-FAST-ISEL-NEXT: i32.const 0 +; NO-FAST-ISEL-NEXT: local.set 0 +; NO-FAST-ISEL-NEXT: i32.const -1 +; NO-FAST-ISEL-NEXT: local.set 1 +; NO-FAST-ISEL-NEXT: local.get 1 +; NO-FAST-ISEL-NEXT: local.get 0 +; NO-FAST-ISEL-NEXT: call foo +; NO-FAST-ISEL-NEXT: local.set 2 +; NO-FAST-ISEL-NEXT: local.get 2 +; NO-FAST-ISEL-NEXT: return start: %0 = call i32 @foo(i1 1, i32 0) ret i32 %0 @@ -63,6 +79,21 @@ define i32 @callsite_signext() { ; CHECK-NEXT: local.set 5 ; CHECK-NEXT: local.get 5 ; CHECK-NEXT: return +; +; NO-FAST-ISEL-LABEL: callsite_signext: +; NO-FAST-ISEL: .functype callsite_signext () -> (i32) +; NO-FAST-ISEL-NEXT: .local i32, i32, i32 +; NO-FAST-ISEL-NEXT: # %bb.0: # %start +; NO-FAST-ISEL-NEXT: i32.const 0 +; NO-FAST-ISEL-NEXT: local.set 0 +; NO-FAST-ISEL-NEXT: i32.const -1 +; NO-FAST-ISEL-NEXT: local.set 1 +; NO-FAST-ISEL-NEXT: local.get 1 +; NO-FAST-ISEL-NEXT: local.get 0 +; NO-FAST-ISEL-NEXT: call foo +; NO-FAST-ISEL-NEXT: local.set 2 +; NO-FAST-ISEL-NEXT: local.get 2 +; NO-FAST-ISEL-NEXT: return start: %0 = call i32 @foo(i1 signext 1, i32 0) ret i32 %0 @@ -93,6 +124,21 @@ define i32 @callsite_nozeroext() { ; CHECK-NEXT: local.set 4 ; CHECK-NEXT: local.get 4 ; CHECK-NEXT: return +; +; NO-FAST-ISEL-LABEL: callsite_nozeroext: +; NO-FAST-ISEL: .functype callsite_nozeroext () -> (i32) +; NO-FAST-ISEL-NEXT: .local i32, i32, i32 +; NO-FAST-ISEL-NEXT: # %bb.0: # %start +; NO-FAST-ISEL-NEXT: i32.const 0 +; NO-FAST-ISEL-NEXT: local.set 0 +; NO-FAST-ISEL-NEXT: i32.const 1 +; NO-FAST-ISEL-NEXT: local.set 1 +; NO-FAST-ISEL-NEXT: local.get 1 +; NO-FAST-ISEL-NEXT: local.get 0 +; NO-FAST-ISEL-NEXT: call foo2 +; NO-FAST-ISEL-NEXT: local.set 2 +; NO-FAST-ISEL-NEXT: local.get 2 +; NO-FAST-ISEL-NEXT: return start: %0 = call i32 @foo2(i1 1, i32 0) ret i32 %0 @@ -119,6 +165,21 @@ define i32 @callsite_zeroext() { ; CHECK-NEXT: local.set 4 ; CHECK-NEXT: local.get 4 ; CHECK-NEXT: return +; +; NO-FAST-ISEL-LABEL: callsite_zeroext: +; NO-FAST-ISEL: .functype callsite_zeroext () -> (i32) +; NO-FAST-ISEL-NEXT: .local i32, i32, i32 +; NO-FAST-ISEL-NEXT: # %bb.0: # %start +; NO-FAST-ISEL-NEXT: i32.const 0 +; NO-FAST-ISEL-NEXT: local.set 0 +; NO-FAST-ISEL-NEXT: i32.const 1 +; NO-FAST-ISEL-NEXT: local.set 1 +; NO-FAST-ISEL-NEXT: local.get 1 +; NO-FAST-ISEL-NEXT: local.get 0 +; NO-FAST-ISEL-NEXT: call foo2 +; NO-FAST-ISEL-NEXT: local.set 2 +; NO-FAST-ISEL-NEXT: local.get 2 +; NO-FAST-ISEL-NEXT: return start: %0 = call i32 @foo2(i1 zeroext 1, i32 0) ret i32 %0 >From b68bf11fb093fefc435e3424d2ba4b05d9bbf39f Mon Sep 17 00:00:00 2001 From: Juneyoung Lee <aqj...@gmail.com> Date: Tue, 9 Jan 2024 17:52:06 -0600 Subject: [PATCH 3/3] Use CallBase::paramHasAttr --- llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp index 80159974ecd691..7f0140a5e8c66f 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -839,11 +839,9 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) { unsigned Reg; - if (Attrs.hasParamAttr(I, Attribute::SExt) || - (IsDirect && Func->hasParamAttribute(I, Attribute::SExt))) + if (Call->paramHasAttr(I, Attribute::SExt)) Reg = getRegForSignedValue(V); - else if (Attrs.hasParamAttr(I, Attribute::ZExt) || - (IsDirect && Func->hasParamAttribute(I, Attribute::ZExt))) + else if (Call->paramHasAttr(I, Attribute::ZExt)) Reg = getRegForUnsignedValue(V); else Reg = getRegForValue(V); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits