Browse Source

[trunk] 'llvm13-13.0.1-1' modify

master
Nathan Owens 1 week ago
parent
commit
c509b3217b
Signed by: ndowens
GPG Key ID: DC5A6F8092641E2D
  1. 4
      .artixlinux/agent.yaml
  2. 4
      Jenkinsfile
  3. 110
      trunk/PKGBUILD
  4. 52
      trunk/disable-A-B-A-B-and-BSWAP-in-InstCombine.patch
  5. 23
      trunk/disable-DIArgList-in-SPIR-V.patch
  6. 63
      trunk/don-t-accept-nullptr-as-GEP-element-type.patch
  7. 91
      trunk/don-t-move-DBG_VALUE-instructions.patch
  8. 540
      trunk/don-t-override-__attribute__-no_stack_protector.patch
  9. 29
      trunk/keys/pgp/474E22316ABF4785A88C6E8EA2C794A986419D8A.asc
  10. 75
      trunk/keys/pgp/B6C8F98282B944E3B0D5C2530FC3042E345AD05D.asc

4
.artixlinux/agent.yaml

@ -0,0 +1,4 @@
---
label: master

4
Jenkinsfile vendored

@ -0,0 +1,4 @@
@Library('artix-ci') import org.artixlinux.RepoPackage
PackagePipeline(new RepoPackage(this))

110
trunk/PKGBUILD

@ -0,0 +1,110 @@
# Maintainer: Nathan Owens <ndowens@artixlinux.org>
# Contributor: Jan "heftig" Steffens <jan.steffens@gmail.com>
pkgname=('llvm13' 'llvm13-libs')
pkgver=13.0.1
pkgrel=1
arch=('x86_64')
url="https://llvm.org/"
license=('custom:Apache 2.0 with LLVM Exception')
makedepends=('cmake' 'ninja' 'libffi' 'libedit' 'ncurses' 'libxml2'
'python')
options=('staticlibs' '!lto') # Getting thousands of test failures with LTO
_source_base=https://github.com/llvm/llvm-project/releases/download/llvmorg-$pkgver
source=($_source_base/llvm-$pkgver.src.tar.xz{,.sig}
don-t-accept-nullptr-as-GEP-element-type.patch
don-t-override-__attribute__-no_stack_protector.patch
don-t-move-DBG_VALUE-instructions.patch
disable-A-B-A-B-and-BSWAP-in-InstCombine.patch
disable-DIArgList-in-SPIR-V.patch)
sha256sums=('ec6b80d82c384acad2dc192903a6cf2cdbaffb889b84bfb98da9d71e630fc834'
'SKIP'
'a7e902a7612d0fdabe436a917468b043cc296bc89d8954bfc3126f737beb9ac4'
'9f0a4578b94eb8853b83af2f65e92705254b4b56d96f9a941714d174b932f465'
'f7d69f84241416398fdb3df8bb44f9fae3c49d89889c7ffa3b37aa2e9d78f708'
'34cc0d79a30599cb2287b47b4e9a1a5bf03d57a1f8bb35be3fe976ffc4a604f6'
'8642da2d556092e4284873ba6ddc6c9a67841f42cc16f923bcd523e4b304a3ff')
validpgpkeys+=('B6C8F98282B944E3B0D5C2530FC3042E345AD05D') # Hans Wennborg <hans@chromium.org>
validpgpkeys+=('474E22316ABF4785A88C6E8EA2C794A986419D8A') # Tom Stellard <tstellar@redhat.com>
prepare() {
cd llvm-$pkgver.src
mkdir build
# https://github.com/intel/intel-graphics-compiler/issues/204
patch -Rp2 -i ../don-t-accept-nullptr-as-GEP-element-type.patch
# Fixes Chromium error "*** stack smashing detected ***: terminated"
# (which also goes away with "--change-stack-guard-on-fork=disabled")
# https://reviews.llvm.org/D116589
patch -Np2 -i ../don-t-override-__attribute__-no_stack_protector.patch
# https://github.com/llvm/llvm-project/issues/53243
# https://github.com/rust-lang/rust/issues/92869
patch -Np2 -i ../don-t-move-DBG_VALUE-instructions.patch
# Patches needed for ISPC for Xe only
patch -Np2 -i ../disable-A-B-A-B-and-BSWAP-in-InstCombine.patch
patch -Np2 -i ../disable-DIArgList-in-SPIR-V.patch
}
build() {
cd llvm-$pkgver.src/build
local cmake_args=(
-G Ninja
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_INSTALL_PREFIX=/usr/lib/llvm13
-DCMAKE_SKIP_RPATH=ON
-DLLVM_BINUTILS_INCDIR=/usr/include
-DLLVM_BUILD_LLVM_DYLIB=ON
-DLLVM_BUILD_TESTS=ON
-DLLVM_ENABLE_BINDINGS=OFF
-DLLVM_ENABLE_FFI=ON
-DLLVM_ENABLE_RTTI=ON
-DLLVM_HOST_TRIPLE=$CHOST
-DLLVM_INSTALL_UTILS=ON
-DLLVM_LINK_LLVM_DYLIB=ON
)
cmake .. "${cmake_args[@]}"
ninja
}
check() {
cd llvm-$pkgver.src/build
LD_LIBRARY_PATH=$PWD/lib ninja check
}
package_llvm13() {
pkgdesc="Compiler infrastructure (LLVM 13)"
depends=('llvm13-libs' 'perl')
cd llvm-$pkgver.src/build
DESTDIR="$pkgdir" ninja install
# The runtime libraries go into llvm13-libs
mv -f "$pkgdir"/usr/lib/llvm13/lib/lib{LLVM,LTO,Remarks}*.so* "$srcdir"
mv -f "$pkgdir"/usr/lib/llvm13/lib/LLVMgold.so "$srcdir"
install -Dm644 ../LICENSE.TXT "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}
package_llvm13-libs() {
pkgdesc="LLVM 13 runtime libraries"
depends=('gcc-libs' 'zlib' 'libffi' 'libedit' 'ncurses' 'libxml2')
install -d "$pkgdir/usr/lib/llvm13/lib"
cp -P \
"$srcdir"/lib{LLVM,LTO,Remarks}*.so* \
"$srcdir"/LLVMgold.so \
"$pkgdir/usr/lib/llvm13/lib/"
install -d "$pkgdir/etc/ld.so.conf.d"
echo /usr/lib/llvm13/lib >"$pkgdir/etc/ld.so.conf.d/llvm13.conf"
install -Dm644 "$srcdir/llvm-$pkgver.src/LICENSE.TXT" \
"$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}
# vim:set ts=2 sw=2 et:

52
trunk/disable-A-B-A-B-and-BSWAP-in-InstCombine.patch

@ -0,0 +1,52 @@
# This patch is needed for ISPC for Xe only
# 1. Transformation of add to or is not safe for VC backend.
# 2. bswap intrinsics is not supported in VC backend yet.
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index d01a021bf3f4..bccce825a03d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -15,6 +15,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Constant.h"
@@ -1369,9 +1370,12 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
}
}
- // A+B --> A|B iff A and B have no bits set in common.
- if (haveNoCommonBitsSet(LHS, RHS, DL, &AC, &I, &DT))
- return BinaryOperator::CreateOr(LHS, RHS);
+ // Disable this transformation for ISPC SPIR-V
+ if (!Triple(I.getModule()->getTargetTriple()).isSPIR()) {
+ // A+B --> A|B iff A and B have no bits set in common.
+ if (haveNoCommonBitsSet(LHS, RHS, DL, &AC, &I, &DT))
+ return BinaryOperator::CreateOr(LHS, RHS);
+ }
// add (select X 0 (sub n A)) A --> select X A n
{
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 120852c44474..8de55311ce3e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2671,9 +2671,12 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
if (Instruction *FoldedLogic = foldBinOpIntoSelectOrPhi(I))
return FoldedLogic;
- if (Instruction *BitOp = matchBSwapOrBitReverse(I, /*MatchBSwaps*/ true,
- /*MatchBitReversals*/ true))
- return BitOp;
+ // Disable this transformation for ISPC SPIR-V
+ if (!Triple(I.getModule()->getTargetTriple()).isSPIR()) {
+ if (Instruction *BitOp = matchBSwapOrBitReverse(I, /*MatchBSwaps*/ true,
+ /*MatchBitReversals*/ true))
+ return BitOp;
+ }
if (Instruction *Funnel = matchFunnelShift(I, *this))
return Funnel;

23
trunk/disable-DIArgList-in-SPIR-V.patch

@ -0,0 +1,23 @@
# This patch is needed for ISPC for Xe only
# It disables using of DIArgList for dbg.val if SPIR-V target is used.
# It is needed till DIArgList is supported in SPIR-V Translator.
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index d03d76f57ca1..0b86e454df57 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -1771,7 +1771,14 @@ void llvm::salvageDebugInfoForDbgValues(
} else if (isa<DbgValueInst>(DII) &&
DII->getNumVariableLocationOps() + AdditionalValues.size() <=
MaxDebugArgs) {
- DII->addVariableLocationOps(AdditionalValues, SalvagedExpr);
+ if (!Triple(I.getModule()->getTargetTriple()).isSPIR()) {
+ DII->addVariableLocationOps(AdditionalValues, SalvagedExpr);
+ } else {
+ // Do not salvage using DIArgList for dbg.val fpr SPIR-V target, as it is
+ // not currently supported by SPIR-V Translator.
+ Value *Undef = UndefValue::get(I.getOperand(0)->getType());
+ DII->replaceVariableLocationOp(I.getOperand(0), Undef);
+ }
} else {
// Do not salvage using DIArgList for dbg.addr/dbg.declare, as it is
// currently only valid for stack value expressions.

63
trunk/don-t-accept-nullptr-as-GEP-element-type.patch

@ -0,0 +1,63 @@
From b00cff56cfb15cbfa74cb512c9cee1c402cce55b Mon Sep 17 00:00:00 2001
From: Nikita Popov <nikita.ppv@gmail.com>
Date: Thu, 8 Jul 2021 20:56:05 +0200
Subject: [PATCH] Reapply [IR] Don't accept nullptr as GEP element type
Reapply after fixing another occurrence in lldb that was relying
on this in the preceding commit.
-----
GetElementPtrInst::Create() (and IRBuilder methods based on it)
currently accept nullptr as the element type, and will fetch the
element type from the pointer in that case. Remove this fallback,
as it is incompatible with opaque pointers. I've removed a handful
of leftover calls using this behavior as a preliminary step.
Out-of-tree code affected by this change should either pass a proper
type, or can temporarily explicitly call getPointerElementType(),
if the newly added assertion is encountered.
Differential Revision: https://reviews.llvm.org/D105653
---
llvm/include/llvm/IR/Instructions.h | 20 ++++++--------------
1 file changed, 6 insertions(+), 14 deletions(-)
diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h
index a5cebf0a4626..0c43a56daa33 100644
--- a/llvm/include/llvm/IR/Instructions.h
+++ b/llvm/include/llvm/IR/Instructions.h
@@ -956,13 +956,9 @@ public:
const Twine &NameStr = "",
Instruction *InsertBefore = nullptr) {
unsigned Values = 1 + unsigned(IdxList.size());
- if (!PointeeType) {
- PointeeType =
- cast<PointerType>(Ptr->getType()->getScalarType())->getElementType();
- } else {
- assert(cast<PointerType>(Ptr->getType()->getScalarType())
- ->isOpaqueOrPointeeTypeMatches(PointeeType));
- }
+ assert(PointeeType && "Must specify element type");
+ assert(cast<PointerType>(Ptr->getType()->getScalarType())
+ ->isOpaqueOrPointeeTypeMatches(PointeeType));
return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values,
NameStr, InsertBefore);
}
@@ -972,13 +968,9 @@ public:
const Twine &NameStr,
BasicBlock *InsertAtEnd) {
unsigned Values = 1 + unsigned(IdxList.size());
- if (!PointeeType) {
- PointeeType =
- cast<PointerType>(Ptr->getType()->getScalarType())->getElementType();
- } else {
- assert(cast<PointerType>(Ptr->getType()->getScalarType())
- ->isOpaqueOrPointeeTypeMatches(PointeeType));
- }
+ assert(PointeeType && "Must specify element type");
+ assert(cast<PointerType>(Ptr->getType()->getScalarType())
+ ->isOpaqueOrPointeeTypeMatches(PointeeType));
return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values,
NameStr, InsertAtEnd);
}

91
trunk/don-t-move-DBG_VALUE-instructions.patch

@ -0,0 +1,91 @@
From e7c9a6cae09d99388d8384ca7c0fb5b24b353975 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov@redhat.com>
Date: Mon, 17 Jan 2022 15:48:01 +0100
Subject: [PATCH] [SDAG] Don't move DBG_VALUE instructions after insertion
point during scheduling (PR53243)
EmitSchedule() shouldn't be touching instructions after the provided
insertion point. The change introduced in D83561 performs a scan to
the end of the block, and thus may move unrelated instructions. In
particular, this ends up moving instructions that have been produced
by FastISel and will later be deleted. Moving them means that more
instructions than intended are removed.
Fix this by stopping the iteration when the insertion point is
reached.
Fixes https://github.com/llvm/llvm-project/issues/53243.
Differential Revision: https://reviews.llvm.org/D117489
---
.../SelectionDAG/ScheduleDAGSDNodes.cpp | 7 ++--
.../CodeGen/X86/pr53243-tail-call-fastisel.ll | 39 +++++++++++++++++++
2 files changed, 43 insertions(+), 3 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/pr53243-tail-call-fastisel.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
index bec240d6c4d4..403f34573899 100644
--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
@@ -1057,12 +1057,13 @@ EmitSchedule(MachineBasicBlock::iterator &InsertPos) {
"first terminator cannot be a debug value");
for (MachineInstr &MI : make_early_inc_range(
make_range(std::next(FirstTerm), InsertBB->end()))) {
+ // Only scan up to insertion point.
+ if (&MI == InsertPos)
+ break;
+
if (!MI.isDebugValue())
continue;
- if (&MI == InsertPos)
- InsertPos = std::prev(InsertPos->getIterator());
-
// The DBG_VALUE was referencing a value produced by a terminator. By
// moving the DBG_VALUE, the referenced value also needs invalidating.
MI.getOperand(0).ChangeToRegister(0, false);
diff --git a/llvm/test/CodeGen/X86/pr53243-tail-call-fastisel.ll b/llvm/test/CodeGen/X86/pr53243-tail-call-fastisel.ll
new file mode 100644
index 000000000000..333eff8fb008
--- /dev/null
+++ b/llvm/test/CodeGen/X86/pr53243-tail-call-fastisel.ll
@@ -0,0 +1,39 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -O0 -fast-isel -mtriple=x86_64-- < %s | FileCheck %s
+
+define void @test() {
+; CHECK-LABEL: test:
+; CHECK: # %bb.0:
+; CHECK-NEXT: jmp set_state@PLT # TAILCALL
+ tail call void @set_state()
+ call void @llvm.dbg.value(metadata i64 0, metadata !10, metadata !DIExpression()), !dbg !16
+ ret void
+}
+
+declare void @set_state()
+
+; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
+declare void @llvm.dbg.value(metadata, metadata, metadata) #0
+
+attributes #0 = { nofree nosync nounwind readnone speculatable willreturn }
+
+!llvm.module.flags = !{!0}
+!llvm.dbg.cu = !{!1}
+
+!0 = !{i32 2, !"Debug Info Version", i32 3}
+!1 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !2, producer: "clang LLVM (rustc version 1.60.0-nightly (ec4bcaac4 2022-01-15))", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !3)
+!2 = !DIFile(filename: "src/lib.rs/@/bug.63e521cd-cgu.0", directory: "/tmp/rust-bug")
+!3 = !{!4}
+!4 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Option", file: !5, baseType: !6, size: 8, align: 8, flags: DIFlagEnumClass, elements: !7)
+!5 = !DIFile(filename: "<unknown>", directory: "")
+!6 = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned)
+!7 = !{!8, !9}
+!8 = !DIEnumerator(name: "None", value: 0)
+!9 = !DIEnumerator(name: "Some", value: 1)
+!10 = !DILocalVariable(name: "msg", arg: 2, scope: !11, file: !12, line: 689, type: !6)
+!11 = distinct !DISubprogram(name: "expect<()>", linkageName: "_ZN4core6option15Option$LT$T$GT$6expect17h9a574c18f194c213E", scope: !4, file: !12, line: 689, type: !13, scopeLine: 689, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !15, retainedNodes: !15)
+!12 = !DIFile(filename: "/rustc/ec4bcaac450279b029f3480b8b8f1b82ab36a5eb/library/core/src/option.rs", directory: "", checksumkind: CSK_MD5, checksum: "4120c8557937a0772190a676ec193800")
+!13 = !DISubroutineType(types: !14)
+!14 = !{null, !4}
+!15 = !{}
+!16 = !DILocation(line: 0, scope: !11)

540
trunk/don-t-override-__attribute__-no_stack_protector.patch

@ -0,0 +1,540 @@
From 4a7c9b7d6f4a183fef8f43aef004ec865c37bbd8 Mon Sep 17 00:00:00 2001
From: Hans Wennborg <hans@chromium.org>
Date: Thu, 13 Jan 2022 11:31:11 +0100
Subject: [PATCH 1/2] Simplify llvm/test/Transforms/Inline/inline_ssp.ll (NFC)
The nounwind and uwtable attributes were just cluttering up the test.
Using regexes to give symbolic names to the attribute lists make the
test more readable.
This is pre-committing parts of D116589.
(cherry picked from commit 2eb7d8d749997e5f3048d39201a4d38b6b8d6455)
---
llvm/test/Transforms/Inline/inline_ssp.ll | 81 +++++++++++------------
1 file changed, 40 insertions(+), 41 deletions(-)
diff --git a/llvm/test/Transforms/Inline/inline_ssp.ll b/llvm/test/Transforms/Inline/inline_ssp.ll
index 2bf93d322842..ccfe93453159 100644
--- a/llvm/test/Transforms/Inline/inline_ssp.ll
+++ b/llvm/test/Transforms/Inline/inline_ssp.ll
@@ -12,150 +12,149 @@
; propagated correctly. The caller should have its SSP attribute set as:
; strictest(caller-ssp-attr, callee-ssp-attr), where strictness is ordered as:
; sspreq > sspstrong > ssp > [no ssp]
-define internal void @fun_sspreq() nounwind sspreq uwtable {
+define internal void @fun_sspreq() sspreq {
entry:
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i32 0, i32 0))
ret void
}
-define internal void @fun_sspstrong() nounwind sspstrong uwtable {
+define internal void @fun_sspstrong() sspstrong {
entry:
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str2, i32 0, i32 0))
ret void
}
-define internal void @fun_ssp() nounwind ssp uwtable {
+define internal void @fun_ssp() ssp {
entry:
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str1, i32 0, i32 0))
ret void
}
-define internal void @fun_nossp() nounwind uwtable {
+define internal void @fun_nossp() {
entry:
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0))
ret void
}
-; Tests start below
+; Tests start below.
-define void @inline_req_req() nounwind sspreq uwtable {
+define void @inline_req_req() sspreq {
entry:
-; CHECK: @inline_req_req() #0
+; CHECK: @inline_req_req() #[[SSPREQ:[0-9]]]
call void @fun_sspreq()
ret void
}
-define void @inline_req_strong() nounwind sspstrong uwtable {
+define void @inline_req_strong() sspstrong {
entry:
-; CHECK: @inline_req_strong() #0
+; CHECK: @inline_req_strong() #[[SSPREQ]]
call void @fun_sspreq()
ret void
}
-define void @inline_req_ssp() nounwind ssp uwtable {
+define void @inline_req_ssp() ssp {
entry:
-; CHECK: @inline_req_ssp() #0
+; CHECK: @inline_req_ssp() #[[SSPREQ]]
call void @fun_sspreq()
ret void
}
-define void @inline_req_nossp() nounwind uwtable {
+define void @inline_req_nossp() {
entry:
-; CHECK: @inline_req_nossp() #3
+; CHECK: @inline_req_nossp() {
call void @fun_sspreq()
ret void
}
-define void @inline_strong_req() nounwind sspreq uwtable {
+define void @inline_strong_req() sspreq {
entry:
-; CHECK: @inline_strong_req() #0
+; CHECK: @inline_strong_req() #[[SSPREQ]]
call void @fun_sspstrong()
ret void
}
-define void @inline_strong_strong() nounwind sspstrong uwtable {
+define void @inline_strong_strong() sspstrong {
entry:
-; CHECK: @inline_strong_strong() #1
+; CHECK: @inline_strong_strong() #[[SSPSTRONG:[0-9]]]
call void @fun_sspstrong()
ret void
}
-define void @inline_strong_ssp() nounwind ssp uwtable {
+define void @inline_strong_ssp() ssp {
entry:
-; CHECK: @inline_strong_ssp() #1
+; CHECK: @inline_strong_ssp() #[[SSPSTRONG]]
call void @fun_sspstrong()
ret void
}
-define void @inline_strong_nossp() nounwind uwtable {
+define void @inline_strong_nossp() {
entry:
-; CHECK: @inline_strong_nossp() #3
+; CHECK: @inline_strong_nossp() {
call void @fun_sspstrong()
ret void
}
-define void @inline_ssp_req() nounwind sspreq uwtable {
+define void @inline_ssp_req() sspreq {
entry:
-; CHECK: @inline_ssp_req() #0
+; CHECK: @inline_ssp_req() #[[SSPREQ]]
call void @fun_ssp()
ret void
}
-define void @inline_ssp_strong() nounwind sspstrong uwtable {
+define void @inline_ssp_strong() sspstrong {
entry:
-; CHECK: @inline_ssp_strong() #1
+; CHECK: @inline_ssp_strong() #[[SSPSTRONG]]
call void @fun_ssp()
ret void
}
-define void @inline_ssp_ssp() nounwind ssp uwtable {
+define void @inline_ssp_ssp() ssp {
entry:
-; CHECK: @inline_ssp_ssp() #2
+; CHECK: @inline_ssp_ssp() #[[SSP:[0-9]]]
call void @fun_ssp()
ret void
}
-define void @inline_ssp_nossp() nounwind uwtable {
+define void @inline_ssp_nossp() {
entry:
-; CHECK: @inline_ssp_nossp() #3
+; CHECK: @inline_ssp_nossp() {
call void @fun_ssp()
ret void
}
-define void @inline_nossp_req() nounwind uwtable sspreq {
+define void @inline_nossp_req() sspreq {
entry:
-; CHECK: @inline_nossp_req() #0
+; CHECK: @inline_nossp_req() #[[SSPREQ]]
call void @fun_nossp()
ret void
}
-define void @inline_nossp_strong() nounwind sspstrong uwtable {
+define void @inline_nossp_strong() sspstrong {
entry:
-; CHECK: @inline_nossp_strong() #1
+; CHECK: @inline_nossp_strong() #[[SSPSTRONG]]
call void @fun_nossp()
ret void
}
-define void @inline_nossp_ssp() nounwind ssp uwtable {
+define void @inline_nossp_ssp() ssp {
entry:
-; CHECK: @inline_nossp_ssp() #2
+; CHECK: @inline_nossp_ssp() #[[SSP]]
call void @fun_nossp()
ret void
}
-define void @inline_nossp_nossp() nounwind uwtable {
+define void @inline_nossp_nossp() {
entry:
-; CHECK: @inline_nossp_nossp() #3
+; CHECK: @inline_nossp_nossp() {
call void @fun_nossp()
ret void
}
declare i32 @printf(i8*, ...)
-; CHECK: attributes #0 = { nounwind sspreq uwtable }
-; CHECK: attributes #1 = { nounwind sspstrong uwtable }
-; CHECK: attributes #2 = { nounwind ssp uwtable }
-; CHECK: attributes #3 = { nounwind uwtable }
+; CHECK: attributes #[[SSPREQ]] = { sspreq }
+; CHECK: attributes #[[SSPSTRONG]] = { sspstrong }
+; CHECK: attributes #[[SSP]] = { ssp }
From b52296ecaa3878648ceeb3aa39df05dc71e44597 Mon Sep 17 00:00:00 2001
From: Hans Wennborg <hans@chromium.org>
Date: Mon, 3 Jan 2022 18:03:43 +0100
Subject: [PATCH 2/2] Don't override __attribute__((no_stack_protector)) by
inlining (PR52886)
Since 26c6a3e736d3, LLVM's inliner will "upgrade" the caller's stack protector
attribute based on the callee. This lead to surprising results with Clang's
no_stack_protector attribute added in 4fbf84c1732f (D46300). Consider the
following code compiled with clang -fstack-protector-strong -Os
(https://godbolt.org/z/7s3rW7a1q).
extern void h(int* p);
inline __attribute__((always_inline)) int g() {
return 0;
}
int __attribute__((__no_stack_protector__)) f() {
int a[1];
h(a);
return g();
}
LLVM will inline g() into f(), and f() would get a stack protector, against the
users explicit wishes, potentially breaking the program e.g. if h() changes the
value of the stack cookie. That's a miscompile.
More recently, bc044a88ee3c (D91816) addressed this problem by preventing
inlining when the stack protector is disabled in the caller and enabled in the
callee or vice versa. However, the problem remained if the callee is marked
always_inline as in the example above. This affected users, see e.g.
http://crbug.com/1274129 and http://llvm.org/pr52886.
One way to fix this would be to prevent inlining also in the always_inline
case. Despite the name, always_inline does not guarantee inlining, so this
would be legal but potentially surprising to users.
However, I think the better fix is to not enable the stack protector in a
caller based on the callee. The motivation for the old behaviour is unclear, it
seems counter-intuitive, and causes real problems as we've seen.
This commit implements that fix, which means in the example above, g() gets
inlined into f() (also without always_inline), and f() is emitted without stack
protector. I think that matches most developers' expectations, and that's also
what GCC does.
Another effect of this change is that a no_stack_protector function can now be
inlined into a stack protected function, e.g. (https://godbolt.org/z/hafP6W856):
extern void h(int* p);
inline int __attribute__((__no_stack_protector__)) __attribute__((always_inline)) g() {
return 0;
}
int f() {
int a[1];
h(a);
return g();
}
I think that's fine. Such code would be unusual since no_stack_protector is
normally applied to a program entry point which sets up the stack canary. And
even if such code exists, inlining doesn't change the semantics: there is still
no stack cookie setup/check around entry/exit of the g() code region, but there
may be in the surrounding context, as there was before inlining. This also
matches GCC.
See also the discussion at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94722
Differential revision: https://reviews.llvm.org/D116589
(cherry picked from commit 2bc57d85ebf244f19a3046295b58eb8c667f947d)
---
llvm/docs/LangRef.rst | 26 +++++------
llvm/lib/Analysis/InlineCost.cpp | 9 ----
llvm/lib/IR/Attributes.cpp | 6 +++
llvm/test/ThinLTO/X86/nossp.ll | 23 ++++++----
llvm/test/Transforms/Inline/inline_nossp.ll | 50 ---------------------
llvm/test/Transforms/Inline/inline_ssp.ll | 19 +++++++-
6 files changed, 48 insertions(+), 85 deletions(-)
delete mode 100644 llvm/test/Transforms/Inline/inline_nossp.ll
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 36e09355e485..69393eba3906 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -1965,11 +1965,9 @@ example:
Variables that are identified as requiring a protector will be arranged
on the stack such that they are adjacent to the stack protector guard.
- A function with the ``ssp`` attribute but without the ``alwaysinline``
- attribute cannot be inlined into a function without a
- ``ssp/sspreq/sspstrong`` attribute. If inlined, the caller will get the
- ``ssp`` attribute. ``call``, ``invoke``, and ``callbr`` instructions with
- the ``alwaysinline`` attribute force inlining.
+ If a function with an ``ssp`` attribute is inlined into a calling function,
+ the attribute is not carried over to the calling function.
+
``sspstrong``
This attribute indicates that the function should emit a stack smashing
protector. This attribute causes a strong heuristic to be used when
@@ -1994,12 +1992,10 @@ example:
This overrides the ``ssp`` function attribute.
- A function with the ``sspstrong`` attribute but without the
- ``alwaysinline`` attribute cannot be inlined into a function without a
- ``ssp/sspstrong/sspreq`` attribute. If inlined, the caller will get the
- ``sspstrong`` attribute unless the ``sspreq`` attribute exists. ``call``,
- ``invoke``, and ``callbr`` instructions with the ``alwaysinline`` attribute
- force inlining.
+ If a function with an ``sspstrong`` attribute is inlined into a calling
+ function which has an ``ssp`` attribute, the calling function's attribute
+ will be upgraded to ``sspstrong``.
+
``sspreq``
This attribute indicates that the function should *always* emit a stack
smashing protector. This overrides the ``ssp`` and ``sspstrong`` function
@@ -2016,11 +2012,9 @@ example:
#. Variables that have had their address taken are 3rd closest to the
protector.
- A function with the ``sspreq`` attribute but without the ``alwaysinline``
- attribute cannot be inlined into a function without a
- ``ssp/sspstrong/sspreq`` attribute. If inlined, the caller will get the
- ``sspreq`` attribute. ``call``, ``invoke``, and ``callbr`` instructions
- with the ``alwaysinline`` attribute force inlining.
+ If a function with an ``sspreq`` attribute is inlined into a calling
+ function which has an ``ssp`` or ``sspstrong`` attribute, the calling
+ function's attribute will be upgraded to ``sspreq``.
``strictfp``
This attribute indicates that the function was called from a scope that
diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp
index e8f79a28a8e8..1e68ec8ff7d6 100644
--- a/llvm/lib/Analysis/InlineCost.cpp
+++ b/llvm/lib/Analysis/InlineCost.cpp
@@ -2823,15 +2823,6 @@ Optional<InlineResult> llvm::getAttributeBasedInliningDecision(
if (Call.isNoInline())
return InlineResult::failure("noinline call site attribute");
- // Don't inline functions if one does not have any stack protector attribute
- // but the other does.
- if (Caller->hasStackProtectorFnAttr() && !Callee->hasStackProtectorFnAttr())
- return InlineResult::failure(
- "stack protected caller but callee requested no stack protector");
- if (Callee->hasStackProtectorFnAttr() && !Caller->hasStackProtectorFnAttr())
- return InlineResult::failure(
- "stack protected callee but caller requested no stack protector");
-
return None;
}
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index 5cd1bafccc47..eec4629aa725 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -1957,6 +1957,12 @@ static void setOR(Function &Caller, const Function &Callee) {
/// If the inlined function had a higher stack protection level than the
/// calling function, then bump up the caller's stack protection level.
static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
+ // If the calling function has *no* stack protection level (e.g. it was built
+ // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
+ // change it as that could change the program's semantics.
+ if (!Caller.hasStackProtectorFnAttr())
+ return;
+
// If upgrading the SSP attribute, clear out the old SSP Attributes first.
// Having multiple SSP attributes doesn't actually hurt, but it adds useless
// clutter to the IR.
diff --git a/llvm/test/ThinLTO/X86/nossp.ll b/llvm/test/ThinLTO/X86/nossp.ll
index c542a85c6f74..cfc54d595ad7 100644
--- a/llvm/test/ThinLTO/X86/nossp.ll
+++ b/llvm/test/ThinLTO/X86/nossp.ll
@@ -23,7 +23,8 @@ declare void @ssp_callee() ssp
; nossp caller should be able to inline nossp callee.
define void @nossp_caller() {
-; CHECK-LABEL: @nossp_caller
+; CHECK-LABEL: define void @nossp_caller()
+; CHECK-NOT: #0
; CHECK-NEXT: tail call void @foo
tail call void @nossp_callee()
ret void
@@ -31,28 +32,34 @@ define void @nossp_caller() {
; ssp caller should be able to inline ssp callee.
define void @ssp_caller() ssp {
-; CHECK-LABEL: @ssp_caller
+; CHECK-LABEL: define void @ssp_caller()
+; CHECK-SAME: #0
; CHECK-NEXT: tail call void @foo
tail call void @ssp_callee()
ret void
}
-; nossp caller should *NOT* be able to inline ssp callee.
+; nossp caller should be able to inline ssp callee.
+; the ssp attribute is not propagated.
define void @nossp_caller2() {
-; CHECK-LABEL: @nossp_caller2
-; CHECK-NEXT: tail call void @ssp_callee
+; CHECK-LABEL: define void @nossp_caller2()
+; CHECK-NOT: #0
+; CHECK-NEXT: tail call void @foo
tail call void @ssp_callee()
ret void
}
-; ssp caller should *NOT* be able to inline nossp callee.
+; ssp caller should be able to inline nossp callee.
define void @ssp_caller2() ssp {
-; CHECK-LABEL: @ssp_caller2
-; CHECK-NEXT: tail call void @nossp_callee
+; CHECK-LABEL: define void @ssp_caller2()
+; CHECK-SAME: #0
+; CHECK-NEXT: tail call void @foo
tail call void @nossp_callee()
ret void
}
+; CHECK: attributes #0 = { ssp }
+
;--- b.ll
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
diff --git a/llvm/test/Transforms/Inline/inline_nossp.ll b/llvm/test/Transforms/Inline/inline_nossp.ll
deleted file mode 100644
index 24fdab0b9f13..000000000000
--- a/llvm/test/Transforms/Inline/inline_nossp.ll
+++ /dev/null
@@ -1,50 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -passes='cgscc(inline)' %s -S -pass-remarks-missed=inline 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-INLINE %s
-; RUN: opt -passes=always-inline -o - -S %s | FileCheck %s
-
-; CHECK-INLINE: ssp not inlined into nossp_caller because it should never be inlined (cost=never): stack protected callee but caller requested no stack protector
-; CHECK-INLINE: nossp not inlined into ssp_caller because it should never be inlined (cost=never): stack protected caller but callee requested no stack protector
-
-; Not interesting to test.
-define i32 @nossp() { ret i32 41 }
-define i32 @ssp() sspstrong { ret i32 42 }
-define i32 @nossp_alwaysinline() alwaysinline { ret i32 43 }
-define i32 @ssp_alwaysinline() sspstrong alwaysinline { ret i32 44 }
-
-; @ssp should not be inlined due to mismatch stack protector.
-; @ssp_alwaysinline should be inlined due to alwaysinline.
-define i32 @nossp_caller() {
-; CHECK-LABEL: @nossp_caller(
-; CHECK-NEXT: [[TMP1:%.*]] = call i32 @ssp()
-; CHECK-NEXT: ret i32 44
-;
- call i32 @ssp()
- %2 = call i32 @ssp_alwaysinline()
- ret i32 %2
-}
-; @nossp should not be inlined due to mismatch stack protector.
-; @nossp_alwaysinline should be inlined due to alwaysinline.
-define i32 @ssp_caller() sspstrong {
-; CHECK-LABEL: @ssp_caller(
-; CHECK-NEXT: [[TMP1:%.*]] = call i32 @nossp()
-; CHECK-NEXT: ret i32 43
-;
- call i32 @nossp()
- %2 = call i32 @nossp_alwaysinline()
- ret i32 %2
-}
-
-; The alwaysinline attribute can also appear on the CallBase (ie. the call
-; site), ie. when __attribute__((flatten)) is used on the caller. Treat this
-; the same as if the caller had the fn attr alwaysinline and permit inline
-; substitution, despite the mismatch between caller and callee on ssp attrs.
-;
-; Curiously, the always_inline attribute on a CallInst is only expanded by the
-; inline pass, but not always_inline pass!
-define i32 @nossp_alwaysinline_caller() {
-; CHECK-INLINE-LABEL: @nossp_alwaysinline_caller(
-; CHECK-INLINE-NEXT: ret i32 42
-;
- %1 = call i32 @ssp() alwaysinline
- ret i32 %1
-}
diff --git a/llvm/test/Transforms/Inline/inline_ssp.ll b/llvm/test/Transforms/Inline/inline_ssp.ll
index ccfe93453159..a4f73f4dcd5a 100644
--- a/llvm/test/Transforms/Inline/inline_ssp.ll
+++ b/llvm/test/Transforms/Inline/inline_ssp.ll
@@ -9,15 +9,23 @@
; These first four functions (@fun_sspreq, @fun_sspstrong, @fun_ssp, @fun_nossp)
; are used by the remaining functions to ensure that the SSP attributes are
-; propagated correctly. The caller should have its SSP attribute set as:
+; propagated correctly. If the caller had an SSP attribute before inlining, it
+; should have its new SSP attribute set as:
; strictest(caller-ssp-attr, callee-ssp-attr), where strictness is ordered as:
-; sspreq > sspstrong > ssp > [no ssp]
+; sspreq > sspstrong > ssp
+
define internal void @fun_sspreq() sspreq {
entry:
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i32 0, i32 0))
ret void
}
+define internal void @fun_sspreq_alwaysinline() sspreq alwaysinline {
+entry:
+ %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i32 0, i32 0))
+ ret void
+}
+
define internal void @fun_sspstrong() sspstrong {
entry:
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str2, i32 0, i32 0))
@@ -66,6 +74,13 @@ entry:
ret void
}
+define void @alwaysinline_req_nossp() {
+entry:
+; CHECK: @alwaysinline_req_nossp() {
+ call void @fun_sspreq_alwaysinline()
+ ret void
+}
+
define void @inline_strong_req() sspreq {
entry:
; CHECK: @inline_strong_req() #[[SSPREQ]]

29
trunk/keys/pgp/474E22316ABF4785A88C6E8EA2C794A986419D8A.asc

@ -0,0 +1,29 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBFrqgT0BEAC7xo0WH+eNrLlU5LrCk59KmImn1abFcmWNd8kYr5XfqmJKyVqo
EY7A/yRjf+Yn1621EDkpKPjbql7q7MlZMpqKVdOWKWgmhvz08IOKJxaIABd/iIRT
FwhIvB68YjtmzcoOJRi1wLnwuG55fJ9E69HyZ33jgAlRaWV3bE/YyszoTlZriUOE
RbzC5WzX004cE9evlrr+YLt5Y6z7tntOdSXPLyGOFAO5LYMsHsEdi2JBYWrjlslG
6iJr5iEt9v442PrJ79YYbu5QWe/6APRWtI3AtKBp7y250oon2lbj+bIVD7U9fOBB
n/Frqx54UN22sJycET63hgYW4pIjIi5zq+FF15aU+ZqBdtNltoX4hEN7wlDpuNc0
ezVu2Z8hdt8thpjiFUioTQ1t3RmsN6N548VwxmHdoYpAmiZqPIYBYvm85JB7S/3h
RLuoeGxufBhXGCpnG8ghTOGtbbdanuLB/UROFXTdyZbTCBN5S6jvwkPSaHG7H35Z
3fazMriTXwL1RGAbKITSWhDe5dXy/yOInWe8emJx+35vwQYCB2L4S8wRyQyRw6x4
YoXCscW041DUMBX2CC7SjMCcmAC39UX1c3GbTpS3rkJR9cmXt50nviMnKpIwlIPd
ZYhmxKifwTJ70+c4GVK2o0MG9bTYvpYhLnYxv6iJCfgmT40E+qkDSzSoZwARAQAB
tCJUb20gU3RlbGxhcmQgPHRzdGVsbGFyQHJlZGhhdC5jb20+iQJWBBMBCABAAhsD
BwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AWIQRHTiIxar9HhaiMbo6ix5SphkGd
igUCYJMrXwUJCWsRIgAKCRCix5SphkGdir/GD/4zT43DAD9GU6VHGFeOphisH2kN
IORVDEn8T+7iR7XLY9nVHJDxqQPUgB/gKYibrVYE0KVqjSSj3dr1cTorubMsDYgy
gjjJSroOZupYC1+Yd8wb0jfdB6Z+CNKh0QN64BDS6D7P1GAcaIbxTyITjoz6jhyF
Lkj4QCLiGWsMbapQA7MB4ij8t/AKORp1kW+tMyn6wfjfmYjrYOyE65UxmJtrV9Fv
YllBt9oCAP0V9qphT6C6wxarJOuhIq9BoZOYKaUa5qRJfzNZagPG8ZalraP/MFfM
g20hLuX5jN1jdzlHEgNt5WCYuI+uekOIUuT1PiFrmWwYXKWMAxnsVefpv8kmW8LR
2TCG+ALvnYCRwr0Ykqh4KZcn4mpsV+QnwNAyVR6Bl6QTsPGtoHkU9Pg640mzkvgg
w55X5kC3x4IxLskD1PFdFpW9LSRL5zz6jT5gL9Eb+zAuKpg/8w64MLnXaX69cR/p
1rrNqZUfBOqf8fbrzy296ZSfeK4tV414iT8j76swQMAONGXoNKxO7E1cAgtxPUWW
u3R4de3sZHGXTiEv70UNRv1TWjlVMK3Av7yDIGUnt+2wi3jilYjLWnAIgSQ46CDQ
tUCdhdwmFcJLa3IJrs/UvHtlq6nU1sIo4wqJwfNBMHx0JZc+bKf41OgYL9ve11F5
IKZNcvom0Pf7MkUKRQ==
=Kuwb
-----END PGP PUBLIC KEY BLOCK-----

75
trunk/keys/pgp/B6C8F98282B944E3B0D5C2530FC3042E345AD05D.asc

@ -0,0 +1,75 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
Qk8uiuyeUfE=
=H/uX
-----END PGP PUBLIC KEY BLOCK-----
Loading…
Cancel
Save