262 changes: 262 additions & 0 deletions flang/test/Integration/OpenMP/parallel-private-reduction-worstcase.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
! RUN: %flang_fc1 -fopenmp -emit-llvm %s -o - | FileCheck %s

! Combinational testing of control flow graph and builder insertion points
! in mlir-to-llvm conversion:
! - mixing multiple delayed privatizations and multiple reductions
! - multiple blocks in the private alloc region
! - private alloc region has to read from the mold variable
! - firstprivate
! - multiple blocks in the private copy region
! - multiple blocks in the reduction init region
! - reduction init region has to read from the mold variable
! - re-used omp.private ops
! - re-used omp.reduction.declare ops
! - unstructured code inside of the parallel region
! - needs private dealloc region, and this has multiple blocks
! - needs reduction cleanup region, and this has multiple blocks

! This maybe belongs in the mlir tests, but what we are doing here is complex
! enough that I find the kind of minimised mlir code preferred by mlir reviewers
! hard to read without some fortran here for reference. Nothing like this would
! be generated by other upstream users of the MLIR OpenMP dialect.

subroutine worst_case(a, b, c, d)
real, allocatable :: a(:), b(:), c(:), d(:)
integer i

!$omp parallel firstprivate(a,b) reduction(+:c,d)
if (sum(a) == 1) stop 1
!$omp end parallel
end subroutine

! CHECK-LABEL: define internal void @worst_case_..omp_par
! CHECK-NEXT: omp.par.entry:
! [reduction alloc regions inlined here]
! CHECK: br label %omp.private.latealloc

! CHECK: omp.private.latealloc: ; preds = %omp.par.entry
! CHECK-NEXT: br label %omp.private.alloc5

! CHECK: omp.private.alloc5: ; preds = %omp.private.latealloc
! [begin private alloc for first var]
! [read the length from the mold argument]
! [if it is non-zero...]
! CHECK: br i1 {{.*}}, label %omp.private.alloc6, label %omp.private.alloc7

! CHECK: omp.private.alloc7: ; preds = %omp.private.alloc5
! [finish private alloc for first var with zero extent]
! CHECK: br label %omp.private.alloc8

! CHECK: omp.private.alloc8: ; preds = %omp.private.alloc6, %omp.private.alloc7
! CHECK-NEXT: br label %omp.region.cont4

! CHECK: omp.region.cont4: ; preds = %omp.private.alloc8
! CHECK-NEXT: %{{.*}} = phi ptr
! CHECK-NEXT: br label %omp.private.alloc

! CHECK: omp.private.alloc: ; preds = %omp.region.cont4
! [begin private alloc for first var]
! [read the length from the mold argument]
! [if it is non-zero...]
! CHECK: br i1 %{{.*}}, label %omp.private.alloc1, label %omp.private.alloc2

! CHECK: omp.private.alloc2: ; preds = %omp.private.alloc
! [finish private alloc for second var with zero extent]
! CHECK: br label %omp.private.alloc3

! CHECK: omp.private.alloc3: ; preds = %omp.private.alloc1, %omp.private.alloc2
! CHECK-NEXT: br label %omp.region.cont

! CHECK: omp.region.cont: ; preds = %omp.private.alloc3
! CHECK-NEXT: %{{.*}} = phi ptr
! CHECK-NEXT: br label %omp.private.copy

! CHECK: omp.private.copy: ; preds = %omp.region.cont
! CHECK-NEXT: br label %omp.private.copy10

! CHECK: omp.private.copy10: ; preds = %omp.private.copy
! [begin firstprivate copy for first var]
! [read the length, is it non-zero?]
! CHECK: br i1 %{{.*}}, label %omp.private.copy11, label %omp.private.copy12

! CHECK: omp.private.copy12: ; preds = %omp.private.copy11, %omp.private.copy10
! CHECK-NEXT: br label %omp.region.cont9

! CHECK: omp.region.cont9: ; preds = %omp.private.copy12
! CHECK-NEXT: %{{.*}} = phi ptr
! CHECK-NEXT: br label %omp.private.copy14

! CHECK: omp.private.copy14: ; preds = %omp.region.cont9
! [begin firstprivate copy for second var]
! [read the length, is it non-zero?]
! CHECK: br i1 %{{.*}}, label %omp.private.copy15, label %omp.private.copy16

! CHECK: omp.private.copy16: ; preds = %omp.private.copy15, %omp.private.copy14
! CHECK-NEXT: br label %omp.region.cont13

! CHECK: omp.region.cont13: ; preds = %omp.private.copy16
! CHECK-NEXT: %{{.*}} = phi ptr
! CHECK-NEXT: br label %omp.reduction.init

! CHECK: omp.reduction.init: ; preds = %omp.region.cont13
! [deffered stores for results of reduction alloc regions]
! CHECK: br label %[[VAL_96:.*]]

! CHECK: omp.reduction.neutral: ; preds = %omp.reduction.init
! [start of reduction initialization region]
! [null check:]
! CHECK: br i1 %{{.*}}, label %omp.reduction.neutral18, label %omp.reduction.neutral19

! CHECK: omp.reduction.neutral19: ; preds = %omp.reduction.neutral
! [malloc and assign the default value to the reduction variable]
! CHECK: br label %omp.reduction.neutral20

! CHECK: omp.reduction.neutral20: ; preds = %omp.reduction.neutral18, %omp.reduction.neutral19
! CHECK-NEXT: br label %omp.region.cont17

! CHECK: omp.region.cont17: ; preds = %omp.reduction.neutral20
! CHECK-NEXT: %{{.*}} = phi ptr
! CHECK-NEXT: br label %omp.reduction.neutral22

! CHECK: omp.reduction.neutral22: ; preds = %omp.region.cont17
! [start of reduction initialization region]
! [null check:]
! CHECK: br i1 %{{.*}}, label %omp.reduction.neutral23, label %omp.reduction.neutral24

! CHECK: omp.reduction.neutral24: ; preds = %omp.reduction.neutral22
! [malloc and assign the default value to the reduction variable]
! CHECK: br label %omp.reduction.neutral25

! CHECK: omp.reduction.neutral25: ; preds = %omp.reduction.neutral23, %omp.reduction.neutral24
! CHECK-NEXT: br label %omp.region.cont21

! CHECK: omp.region.cont21: ; preds = %omp.reduction.neutral25
! CHECK-NEXT: %{{.*}} = phi ptr
! CHECK-NEXT: br label %omp.par.region

! CHECK: omp.par.region: ; preds = %omp.region.cont21
! CHECK-NEXT: br label %omp.par.region27

! CHECK: omp.par.region27: ; preds = %omp.par.region
! [call SUM runtime function]
! [if (sum(a) == 1)]
! CHECK: br i1 %{{.*}}, label %omp.par.region28, label %omp.par.region29

! CHECK: omp.par.region29: ; preds = %omp.par.region27
! CHECK-NEXT: br label %omp.region.cont26

! CHECK: omp.region.cont26: ; preds = %omp.par.region28, %omp.par.region29
! [omp parallel region done, call into the runtime to complete reduction]
! CHECK: %[[VAL_233:.*]] = call i32 @__kmpc_reduce(
! CHECK: switch i32 %[[VAL_233]], label %reduce.finalize [
! CHECK-NEXT: i32 1, label %reduce.switch.nonatomic
! CHECK-NEXT: i32 2, label %reduce.switch.atomic
! CHECK-NEXT: ]

! CHECK: reduce.switch.atomic: ; preds = %omp.region.cont26
! CHECK-NEXT: unreachable

! CHECK: reduce.switch.nonatomic: ; preds = %omp.region.cont26
! CHECK-NEXT: %[[red_private_value_0:.*]] = load ptr, ptr %{{.*}}, align 8
! CHECK-NEXT: br label %omp.reduction.nonatomic.body

! [various blocks implementing the reduction]

! CHECK: omp.region.cont35: ; preds =
! CHECK-NEXT: %{{.*}} = phi ptr
! CHECK-NEXT: call void @__kmpc_end_reduce(
! CHECK-NEXT: br label %reduce.finalize

! CHECK: reduce.finalize: ; preds =
! CHECK-NEXT: br label %omp.par.pre_finalize

! CHECK: omp.par.pre_finalize: ; preds = %reduce.finalize
! CHECK-NEXT: %{{.*}} = load ptr, ptr
! CHECK-NEXT: br label %omp.reduction.cleanup

! CHECK: omp.reduction.cleanup: ; preds = %omp.par.pre_finalize
! [null check]
! CHECK: br i1 %{{.*}}, label %omp.reduction.cleanup41, label %omp.reduction.cleanup42

! CHECK: omp.reduction.cleanup42: ; preds = %omp.reduction.cleanup41, %omp.reduction.cleanup
! CHECK-NEXT: br label %omp.region.cont40

! CHECK: omp.region.cont40: ; preds = %omp.reduction.cleanup42
! CHECK-NEXT: %{{.*}} = load ptr, ptr
! CHECK-NEXT: br label %omp.reduction.cleanup44

! CHECK: omp.reduction.cleanup44: ; preds = %omp.region.cont40
! [null check]
! CHECK: br i1 %{{.*}}, label %omp.reduction.cleanup45, label %omp.reduction.cleanup46

! CHECK: omp.reduction.cleanup46: ; preds = %omp.reduction.cleanup45, %omp.reduction.cleanup44
! CHECK-NEXT: br label %omp.region.cont43

! CHECK: omp.region.cont43: ; preds = %omp.reduction.cleanup46
! CHECK-NEXT: br label %omp.private.dealloc

! CHECK: omp.private.dealloc: ; preds = %omp.region.cont43
! [null check]
! CHECK: br i1 %{{.*}}, label %omp.private.dealloc48, label %omp.private.dealloc49

! CHECK: omp.private.dealloc49: ; preds = %omp.private.dealloc48, %omp.private.dealloc
! CHECK-NEXT: br label %omp.region.cont47

! CHECK: omp.region.cont47: ; preds = %omp.private.dealloc49
! CHECK-NEXT: br label %omp.private.dealloc51

! CHECK: omp.private.dealloc51: ; preds = %omp.region.cont47
! [null check]
! CHECK: br i1 %{{.*}}, label %omp.private.dealloc52, label %omp.private.dealloc53

! CHECK: omp.private.dealloc53: ; preds = %omp.private.dealloc52, %omp.private.dealloc51
! CHECK-NEXT: br label %omp.region.cont50

! CHECK: omp.region.cont50: ; preds = %omp.private.dealloc53
! CHECK-NEXT: br label %omp.par.outlined.exit.exitStub

! CHECK: omp.private.dealloc52: ; preds = %omp.private.dealloc51
! [dealloc memory]
! CHECK: br label %omp.private.dealloc53

! CHECK: omp.private.dealloc48: ; preds = %omp.private.dealloc
! [dealloc memory]
! CHECK: br label %omp.private.dealloc49

! CHECK: omp.reduction.cleanup45: ; preds = %omp.reduction.cleanup44
! CHECK-NEXT: call void @free(
! CHECK-NEXT: br label %omp.reduction.cleanup46

! CHECK: omp.reduction.cleanup41: ; preds = %omp.reduction.cleanup
! CHECK-NEXT: call void @free(
! CHECK-NEXT: br label %omp.reduction.cleanup42

! CHECK: omp.par.region28: ; preds = %omp.par.region27
! CHECK-NEXT: call {} @_FortranAStopStatement

! CHECK: omp.reduction.neutral23: ; preds = %omp.reduction.neutral22
! [source length was zero: finish initializing array]
! CHECK: br label %omp.reduction.neutral25

! CHECK: omp.reduction.neutral18: ; preds = %omp.reduction.neutral
! [source length was zero: finish initializing array]
! CHECK: br label %omp.reduction.neutral20

! CHECK: omp.private.copy15: ; preds = %omp.private.copy14
! [source length was non-zero: call assign runtime]
! CHECK: br label %omp.private.copy16

! CHECK: omp.private.copy11: ; preds = %omp.private.copy10
! [source length was non-zero: call assign runtime]
! CHECK: br label %omp.private.copy12

! CHECK: omp.private.alloc1: ; preds = %omp.private.alloc
! [var extent was non-zero: malloc a private array]
! CHECK: br label %omp.private.alloc3

! CHECK: omp.private.alloc6: ; preds = %omp.private.alloc5
! [var extent was non-zero: malloc a private array]
! CHECK: br label %omp.private.alloc8

! CHECK: omp.par.outlined.exit.exitStub: ; preds = %omp.region.cont50
! CHECK-NEXT: ret void
46 changes: 46 additions & 0 deletions flang/test/Integration/OpenMP/private-global.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
!RUN: %flang_fc1 -emit-llvm -fopenmp %s -o - | FileCheck %s

! Regression test for https://github.com/llvm/llvm-project/issues/106297

program bug
implicit none
integer :: table(10)
!$OMP PARALLEL PRIVATE(table)
table = 50
if (any(table/=50)) then
stop 'fail 3'
end if
!$OMP END PARALLEL
print *,'ok'
End Program


! CHECK-LABEL: define internal void {{.*}}..omp_par(
! CHECK: omp.par.entry:
! CHECK: %[[VAL_9:.*]] = alloca i32, align 4
! CHECK: %[[VAL_10:.*]] = load i32, ptr %[[VAL_11:.*]], align 4
! CHECK: store i32 %[[VAL_10]], ptr %[[VAL_9]], align 4
! CHECK: %[[VAL_12:.*]] = load i32, ptr %[[VAL_9]], align 4
! CHECK: %[[PRIV_TABLE:.*]] = alloca [10 x i32], i64 1, align 4
! ...
! check that we use the private copy of table for the assignment
! CHECK: omp.par.region1:
! CHECK: %[[ELEMENTAL_TMP:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, align 8
! CHECK: %[[TABLE_BOX_ADDR:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, align 8
! CHECK: %[[BOXED_FIFTY:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8 }, align 8
! CHECK: %[[TABLE_BOX_ADDR2:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, i64 1, align 8
! CHECK: %[[TABLE_BOX_VAL:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } { ptr undef, i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64), i32 20240719, i8 1, i8 9, i8 0, i8 0, [1 x [3 x i64]] {{\[\[}}3 x i64] [i64 1, i64 10, i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64)]] }, ptr %[[PRIV_TABLE]], 0
! CHECK: store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[TABLE_BOX_VAL]], ptr %[[TABLE_BOX_ADDR]], align 8
! CHECK: %[[TABLE_BOX_VAL2:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[TABLE_BOX_ADDR]], align 8
! CHECK: store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[TABLE_BOX_VAL2]], ptr %[[TABLE_BOX_ADDR2]], align 8
! CHECK: %[[VAL_26:.*]] = call {} @_FortranAAssign(ptr %[[TABLE_BOX_ADDR2]], ptr %[[BOXED_FIFTY]], ptr @{{.*}}, i32 9)
! ...
! check that we use the private copy of table for table/=50
! CHECK: omp.par.region3:
! CHECK: %[[VAL_44:.*]] = sub nsw i64 %{{.*}}, 1
! CHECK: %[[VAL_45:.*]] = mul nsw i64 %[[VAL_44]], 1
! CHECK: %[[VAL_46:.*]] = mul nsw i64 %[[VAL_45]], 1
! CHECK: %[[VAL_47:.*]] = add nsw i64 %[[VAL_46]], 0
! CHECK: %[[VAL_48:.*]] = getelementptr i32, ptr %[[PRIV_TABLE]], i64 %[[VAL_47]]
! CHECK: %[[VAL_49:.*]] = load i32, ptr %[[VAL_48]], align 4
! CHECK: %[[VAL_50:.*]] = icmp ne i32 %[[VAL_49]], 50
24 changes: 24 additions & 0 deletions flang/test/Lower/OpenMP/simd.f90
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
! RUN: %flang_fc1 -flang-experimental-hlfir -emit-hlfir -fopenmp -fopenmp-version=50 %s -o - | FileCheck %s
! RUN: bbc -hlfir -emit-hlfir -fopenmp -fopenmp-version=50 %s -o - | FileCheck %s

!CHECK: omp.declare_reduction @[[REDUCER:.*]] : i32

!CHECK-LABEL: func @_QPsimd()
subroutine simd
integer :: i
Expand Down Expand Up @@ -273,3 +275,25 @@ subroutine lastprivate_with_simd
sum = i + 1
end do
end subroutine

!CHECK-LABEL: func @_QPsimd_with_reduction_clause()
subroutine simd_with_reduction_clause
integer :: i, x
x = 0
! CHECK: %[[LB:.*]] = arith.constant 1 : i32
! CHECK-NEXT: %[[UB:.*]] = arith.constant 9 : i32
! CHECK-NEXT: %[[STEP:.*]] = arith.constant 1 : i32
! CHECK-NEXT: omp.simd reduction(@[[REDUCER]] %[[X:.*]]#0 -> %[[X_RED:.*]] : !fir.ref<i32>) {
! CHECK-NEXT: omp.loop_nest (%[[I:.*]]) : i32 = (%[[LB]]) to (%[[UB]]) inclusive step (%[[STEP]]) {
!$omp simd reduction(+:x)
do i=1, 9
! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X_RED]] {uniq_name = "_QFsimd_with_reduction_clauseEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: fir.store %[[I]] to %[[LOCAL:.*]]#1 : !fir.ref<i32>
! CHECK: %[[X_LD:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref<i32>
! CHECK: %[[I_LD:.*]] = fir.load %[[LOCAL]]#0 : !fir.ref<i32>
! CHECK: %[[SUM:.*]] = arith.addi %[[X_LD]], %[[I_LD]] : i32
! CHECK: hlfir.assign %[[SUM]] to %[[X_DECL]]#0 : i32, !fir.ref<i32>
x = x+i
end do
!$OMP end simd
end subroutine
1 change: 1 addition & 0 deletions libc/config/gpu/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.ceilf16
libc.src.math.copysignf16
libc.src.math.exp10f16
libc.src.math.exp10m1f16
libc.src.math.exp2f16
libc.src.math.expf16
libc.src.math.f16add
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.ceilf16
libc.src.math.copysignf16
libc.src.math.exp10f16
libc.src.math.exp10m1f16
libc.src.math.exp2f16
libc.src.math.exp2m1f16
libc.src.math.expf16
Expand Down
2 changes: 1 addition & 1 deletion libc/docs/math/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ Higher Math Functions
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| exp10 | |check| | |check| | | |check| | | 7.12.6.2 | F.10.3.2 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| exp10m1 | | | | | | 7.12.6.3 | F.10.3.3 |
| exp10m1 | | | | |check| | | 7.12.6.3 | F.10.3.3 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| exp2 | |check| | |check| | | |check| | | 7.12.6.4 | F.10.3.4 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
Expand Down
2 changes: 2 additions & 0 deletions libc/spec/stdc.td
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,8 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"exp10f", RetValSpec<FloatType>, [ArgSpec<FloatType>]>,
GuardedFunctionSpec<"exp10f16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,

GuardedFunctionSpec<"exp10m1f16", RetValSpec<Float16Type>, [ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,

FunctionSpec<"remainder", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"remainderf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
FunctionSpec<"remainderl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
Expand Down
2 changes: 2 additions & 0 deletions libc/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ add_math_entrypoint_object(exp10)
add_math_entrypoint_object(exp10f)
add_math_entrypoint_object(exp10f16)

add_math_entrypoint_object(exp10m1f16)

add_math_entrypoint_object(expm1)
add_math_entrypoint_object(expm1f)
add_math_entrypoint_object(expm1f16)
Expand Down
21 changes: 21 additions & 0 deletions libc/src/math/exp10m1f16.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for exp10m1f16 --------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_MATH_EXP10M1F16_H
#define LLVM_LIBC_SRC_MATH_EXP10M1F16_H

#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/types.h"

namespace LIBC_NAMESPACE_DECL {

float16 exp10m1f16(float16 x);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_MATH_EXP10M1F16_H
23 changes: 23 additions & 0 deletions libc/src/math/generic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1656,6 +1656,29 @@ add_entrypoint_object(
-O3
)

add_entrypoint_object(
exp10m1f16
SRCS
exp10m1f16.cpp
HDRS
../exp10m1f16.h
DEPENDS
.expxf16
libc.hdr.errno_macros
libc.hdr.fenv_macros
libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.except_value_utils
libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.multiply_add
libc.src.__support.FPUtil.polyeval
libc.src.__support.FPUtil.rounding_mode
libc.src.__support.macros.optimization
libc.src.__support.macros.properties.cpu_features
COMPILE_OPTIONS
-O3
)

add_entrypoint_object(
expm1
SRCS
Expand Down
47 changes: 3 additions & 44 deletions libc/src/math/generic/exp10f16.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,6 @@ static constexpr fputil::ExceptValues<float16, N_EXP10F16_EXCEPTS>
#endif
}};

// Generated by Sollya with the following commands:
// > display = hexadecimal;
// > round(log2(10), SG, RN);
static constexpr float LOG2F_10 = 0x1.a934fp+1f;

// Generated by Sollya with the following commands:
// > display = hexadecimal;
// > round(log10(2), SG, RN);
static constexpr float LOG10F_2 = 0x1.344136p-2f;

LLVM_LIBC_FUNCTION(float16, exp10f16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
FPBits x_bits(x);
Expand Down Expand Up @@ -132,40 +122,9 @@ LLVM_LIBC_FUNCTION(float16, exp10f16, (float16 x)) {
if (auto r = EXP10F16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();

// For -8 < x < 5, to compute 10^x, we perform the following range reduction:
// find hi, mid, lo, such that:
// x = (hi + mid) * log2(10) + lo, in which
// hi is an integer,
// mid * 2^3 is an integer,
// -2^(-4) <= lo < 2^(-4).
// In particular,
// hi + mid = round(x * 2^3) * 2^(-3).
// Then,
// 10^x = 10^(hi + mid + lo) = 2^((hi + mid) * log2(10)) + 10^lo
// We store 2^mid in the lookup table EXP2_MID_BITS, and compute 2^hi * 2^mid
// by adding hi to the exponent field of 2^mid. 10^lo is computed using a
// degree-4 minimax polynomial generated by Sollya.

float xf = x;
float kf = fputil::nearest_integer(xf * (LOG2F_10 * 0x1.0p+3f));
int x_hi_mid = static_cast<int>(kf);
int x_hi = x_hi_mid >> 3;
int x_mid = x_hi_mid & 0x7;
// lo = x - (hi + mid) = round(x * 2^3 * log2(10)) * log10(2) * (-2^(-3)) + x
float lo = fputil::multiply_add(kf, LOG10F_2 * -0x1.0p-3f, xf);

uint32_t exp2_hi_mid_bits =
EXP2_MID_BITS[x_mid] +
static_cast<uint32_t>(x_hi << fputil::FPBits<float>::FRACTION_LEN);
float exp2_hi_mid = fputil::FPBits<float>(exp2_hi_mid_bits).get_val();
// Degree-4 minimax polynomial generated by Sollya with the following
// commands:
// > display = hexadecimal;
// > P = fpminimax((10^x - 1)/x, 3, [|SG...|], [-2^-4, 2^-4]);
// > 1 + x * P;
float exp10_lo = fputil::polyeval(lo, 0x1p+0f, 0x1.26bb14p+1f, 0x1.53526p+1f,
0x1.04b434p+1f, 0x1.2bcf9ep+0f);
return fputil::cast<float16>(exp2_hi_mid * exp10_lo);
// 10^x = 2^((hi + mid) * log2(10)) * 10^lo
auto [exp2_hi_mid, exp10_lo] = exp10_range_reduction(x);
return static_cast<float16>(exp2_hi_mid * exp10_lo);
}

} // namespace LIBC_NAMESPACE_DECL
163 changes: 163 additions & 0 deletions libc/src/math/generic/exp10m1f16.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
//===-- Half-precision 10^x - 1 function ----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/math/exp10m1f16.h"
#include "expxf16.h"
#include "hdr/errno_macros.h"
#include "hdr/fenv_macros.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/PolyEval.h"
#include "src/__support/FPUtil/cast.h"
#include "src/__support/FPUtil/except_value_utils.h"
#include "src/__support/FPUtil/multiply_add.h"
#include "src/__support/FPUtil/rounding_mode.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h"
#include "src/__support/macros/properties/cpu_features.h"

namespace LIBC_NAMESPACE_DECL {

static constexpr fputil::ExceptValues<float16, 3> EXP10M1F16_EXCEPTS_LO = {{
// (input, RZ output, RU offset, RD offset, RN offset)
// x = 0x1.5c4p-4, exp10m1f16(x) = 0x1.bacp-3 (RZ)
{0x2d71U, 0x32ebU, 1U, 0U, 0U},
// x = -0x1.5ep-13, exp10m1f16(x) = -0x1.92cp-12 (RZ)
{0x8978U, 0x8e4bU, 0U, 1U, 0U},
// x = -0x1.e2p-10, exp10m1f16(x) = -0x1.14cp-8 (RZ)
{0x9788U, 0x9c53U, 0U, 1U, 0U},
}};

#ifdef LIBC_TARGET_CPU_HAS_FMA
static constexpr size_t N_EXP10M1F16_EXCEPTS_HI = 3;
#else
static constexpr size_t N_EXP10M1F16_EXCEPTS_HI = 6;
#endif

static constexpr fputil::ExceptValues<float16, N_EXP10M1F16_EXCEPTS_HI>
EXP10M1F16_EXCEPTS_HI = {{
// (input, RZ output, RU offset, RD offset, RN offset)
// x = 0x1.8f4p-2, exp10m1f16(x) = 0x1.744p+0 (RZ)
{0x363dU, 0x3dd1U, 1U, 0U, 0U},
// x = 0x1.95cp-2, exp10m1f16(x) = 0x1.7d8p+0 (RZ)
{0x3657U, 0x3df6U, 1U, 0U, 0U},
// x = 0x1.d04p-2, exp10m1f16(x) = 0x1.d7p+0 (RZ)
{0x3741U, 0x3f5cU, 1U, 0U, 1U},
#ifndef LIBC_TARGET_CPU_HAS_FMA
// x = 0x1.0cp+1, exp10m1f16(x) = 0x1.ec4p+6 (RZ)
{0x4030U, 0x57b1U, 1U, 0U, 1U},
// x = 0x1.1b8p+1, exp10m1f16(x) = 0x1.45cp+7 (RZ)
{0x406eU, 0x5917U, 1U, 0U, 1U},
// x = 0x1.2f4p+2, exp10m1f16(x) = 0x1.ab8p+15 (RZ)
{0x44bdU, 0x7aaeU, 1U, 0U, 1U},
#endif
}};

LLVM_LIBC_FUNCTION(float16, exp10m1f16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
FPBits x_bits(x);

uint16_t x_u = x_bits.uintval();
uint16_t x_abs = x_u & 0x7fffU;

// When |x| <= 2^(-3), or |x| >= 11 * log10(2), or x is NaN.
if (LIBC_UNLIKELY(x_abs <= 0x3000U || x_abs >= 0x429fU)) {
// exp10m1(NaN) = NaN
if (x_bits.is_nan()) {
if (x_bits.is_signaling_nan()) {
fputil::raise_except_if_required(FE_INVALID);
return FPBits::quiet_nan().get_val();
}

return x;
}

// When x >= 16 * log10(2).
if (x_u >= 0x44d1U && x_bits.is_pos()) {
// exp10m1(+inf) = +inf
if (x_bits.is_inf())
return FPBits::inf().get_val();

switch (fputil::quick_get_round()) {
case FE_TONEAREST:
case FE_UPWARD:
fputil::set_errno_if_required(ERANGE);
fputil::raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
return FPBits::inf().get_val();
default:
return FPBits::max_normal().get_val();
}
}

// When x < -11 * log10(2).
if (x_u > 0xc29fU) {
// exp10m1(-inf) = -1
if (x_bits.is_inf())
return FPBits::one(Sign::NEG).get_val();

// When x >= -0x1.ce4p+1, round(10^x - 1, HP, RN) = -0x1.ffcp-1.
if (x_u <= 0xc339U) {
return fputil::round_result_slightly_down(
fputil::cast<float16>(-0x1.ffcp-1));
}

// When x < -0x1.ce4p+1, round(10^x - 1, HP, RN) = -1.
switch (fputil::quick_get_round()) {
case FE_TONEAREST:
case FE_DOWNWARD:
return FPBits::one(Sign::NEG).get_val();
default:
return fputil::cast<float16>(-0x1.ffcp-1);
}
}

// When |x| <= 2^(-3).
if (x_abs <= 0x3000U) {
if (auto r = EXP10M1F16_EXCEPTS_LO.lookup(x_u);
LIBC_UNLIKELY(r.has_value()))
return r.value();

float xf = x;
// Degree-5 minimax polynomial generated by Sollya with the following
// commands:
// > display = hexadecimal;
// > P = fpminimax((10^x - 1)/x, 4, [|SG...|], [-2^-3, 2^-3]);
// > x * P;
return fputil::cast<float16>(
xf * fputil::polyeval(xf, 0x1.26bb1cp+1f, 0x1.5351c8p+1f,
0x1.04704p+1f, 0x1.2ce084p+0f, 0x1.14a6bep-1f));
}
}

// When x is 1, 2, or 3. These are hard-to-round cases with exact results.
// 10^4 - 1 = 9'999 is not exactly representable as a float16, but luckily the
// polynomial approximation gives the correct result for x = 4 in all
// rounding modes.
if (LIBC_UNLIKELY((x_u & ~(0x3c00U | 0x4000U | 0x4200U | 0x4400U)) == 0)) {
switch (x_u) {
case 0x3c00U: // x = 1.0f16
return fputil::cast<float16>(9.0);
case 0x4000U: // x = 2.0f16
return fputil::cast<float16>(99.0);
case 0x4200U: // x = 3.0f16
return fputil::cast<float16>(999.0);
}
}

if (auto r = EXP10M1F16_EXCEPTS_HI.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();

// exp10(x) = exp2((hi + mid) * log2(10)) * exp10(lo)
auto [exp2_hi_mid, exp10_lo] = exp10_range_reduction(x);
// exp10m1(x) = exp2((hi + mid) * log2(lo)) * exp10(lo) - 1
return fputil::cast<float16>(
fputil::multiply_add(exp2_hi_mid, exp10_lo, -1.0f));
}

} // namespace LIBC_NAMESPACE_DECL
47 changes: 47 additions & 0 deletions libc/src/math/generic/expxf16.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,53 @@ LIBC_INLINE ExpRangeReduction exp2_range_reduction(float16 x) {
return {exp2_hi_mid, exp2_lo};
}

// Generated by Sollya with the following commands:
// > display = hexadecimal;
// > round(log2(10), SG, RN);
static constexpr float LOG2F_10 = 0x1.a934fp+1f;

// Generated by Sollya with the following commands:
// > display = hexadecimal;
// > round(log10(2), SG, RN);
static constexpr float LOG10F_2 = 0x1.344136p-2f;

LIBC_INLINE ExpRangeReduction exp10_range_reduction(float16 x) {
// For -8 < x < 5, to compute 10^x, we perform the following range reduction:
// find hi, mid, lo, such that:
// x = (hi + mid) * log2(10) + lo, in which
// hi is an integer,
// mid * 2^3 is an integer,
// -2^(-4) <= lo < 2^(-4).
// In particular,
// hi + mid = round(x * 2^3) * 2^(-3).
// Then,
// 10^x = 10^(hi + mid + lo) = 2^((hi + mid) * log2(10)) + 10^lo
// We store 2^mid in the lookup table EXP2_MID_BITS, and compute 2^hi * 2^mid
// by adding hi to the exponent field of 2^mid. 10^lo is computed using a
// degree-4 minimax polynomial generated by Sollya.

float xf = x;
float kf = fputil::nearest_integer(xf * (LOG2F_10 * 0x1.0p+3f));
int x_hi_mid = static_cast<int>(kf);
int x_hi = x_hi_mid >> 3;
int x_mid = x_hi_mid & 0x7;
// lo = x - (hi + mid) = round(x * 2^3 * log2(10)) * log10(2) * (-2^(-3)) + x
float lo = fputil::multiply_add(kf, LOG10F_2 * -0x1.0p-3f, xf);

uint32_t exp2_hi_mid_bits =
EXP2_MID_BITS[x_mid] +
static_cast<uint32_t>(x_hi << fputil::FPBits<float>::FRACTION_LEN);
float exp2_hi_mid = fputil::FPBits<float>(exp2_hi_mid_bits).get_val();
// Degree-4 minimax polynomial generated by Sollya with the following
// commands:
// > display = hexadecimal;
// > P = fpminimax((10^x - 1)/x, 3, [|SG...|], [-2^-4, 2^-4]);
// > 1 + x * P;
float exp10_lo = fputil::polyeval(lo, 0x1p+0f, 0x1.26bb14p+1f, 0x1.53526p+1f,
0x1.04b434p+1f, 0x1.2bcf9ep+0f);
return {exp2_hi_mid, exp10_lo};
}

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_MATH_GENERIC_EXPXF16_H
11 changes: 11 additions & 0 deletions libc/test/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1062,6 +1062,17 @@ add_fp_unittest(
libc.src.math.exp10f16
)

add_fp_unittest(
exp10m1f16_test
NEED_MPFR
SUITE
libc-math-unittests
SRCS
exp10m1f16_test.cpp
DEPENDS
libc.src.math.exp10m1f16
)

add_fp_unittest(
copysign_test
SUITE
Expand Down
40 changes: 40 additions & 0 deletions libc/test/src/math/exp10m1f16_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//===-- Exhaustive test for exp10m1f16 ------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/math/exp10m1f16.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include "utils/MPFRWrapper/MPFRUtils.h"

using LlvmLibcExp10m1f16Test = LIBC_NAMESPACE::testing::FPTest<float16>;

namespace mpfr = LIBC_NAMESPACE::testing::mpfr;

// Range: [0, Inf];
static constexpr uint16_t POS_START = 0x0000U;
static constexpr uint16_t POS_STOP = 0x7c00U;

// Range: [-Inf, 0];
static constexpr uint16_t NEG_START = 0x8000U;
static constexpr uint16_t NEG_STOP = 0xfc00U;

TEST_F(LlvmLibcExp10m1f16Test, PositiveRange) {
for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
float16 x = FPBits(v).get_val();
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp10m1, x,
LIBC_NAMESPACE::exp10m1f16(x), 0.5);
}
}

TEST_F(LlvmLibcExp10m1f16Test, NegativeRange) {
for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
float16 x = FPBits(v).get_val();
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp10m1, x,
LIBC_NAMESPACE::exp10m1f16(x), 0.5);
}
}
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1235,6 +1235,19 @@ add_fp_unittest(
libc.src.__support.FPUtil.cast
)

add_fp_unittest(
exp10m1f16_test
SUITE
libc-math-smoke-tests
SRCS
exp10m1f16_test.cpp
DEPENDS
libc.hdr.fenv_macros
libc.src.errno.errno
libc.src.math.exp10m1f16
libc.src.__support.FPUtil.cast
)

add_fp_unittest(
copysign_test
SUITE
Expand Down
113 changes: 113 additions & 0 deletions libc/test/src/math/smoke/exp10m1f16_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//===-- Unittests for exp10m1f16 ------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "hdr/fenv_macros.h"
#include "src/__support/FPUtil/cast.h"
#include "src/errno/libc_errno.h"
#include "src/math/exp10m1f16.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

using LlvmLibcExp10m1f16Test = LIBC_NAMESPACE::testing::FPTest<float16>;

TEST_F(LlvmLibcExp10m1f16Test, SpecialNumbers) {
LIBC_NAMESPACE::libc_errno = 0;

EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::exp10m1f16(aNaN));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::exp10m1f16(sNaN),
FE_INVALID);
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::exp10m1f16(inf));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(LIBC_NAMESPACE::fputil::cast<float16>(-1.0),
LIBC_NAMESPACE::exp10m1f16(neg_inf));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::exp10m1f16(zero));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, LIBC_NAMESPACE::exp10m1f16(neg_zero));
EXPECT_MATH_ERRNO(0);
}

TEST_F(LlvmLibcExp10m1f16Test, Overflow) {
LIBC_NAMESPACE::libc_errno = 0;

EXPECT_FP_EQ_WITH_EXCEPTION(inf, LIBC_NAMESPACE::exp10m1f16(max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);

// round(16 * log10(2), HP, RN);
float16 x = LIBC_NAMESPACE::fputil::cast<float16>(0x1.344p+2);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_NEAREST(
inf, LIBC_NAMESPACE::exp10m1f16(x), FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD(
inf, LIBC_NAMESPACE::exp10m1f16(x), FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_DOWNWARD(
max_normal, LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_TOWARD_ZERO(
max_normal, LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);
EXPECT_MATH_ERRNO(0);
}

TEST_F(LlvmLibcExp10m1f16Test, ResultNearNegOne) {
LIBC_NAMESPACE::libc_errno = 0;

EXPECT_FP_EQ_WITH_EXCEPTION(LIBC_NAMESPACE::fputil::cast<float16>(-1.0),
LIBC_NAMESPACE::exp10m1f16(neg_max_normal),
FE_INEXACT);

// round(-11 * log10(2), HP, RD);
float16 x = LIBC_NAMESPACE::fputil::cast<float16>(-0x1.a8p+1);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_NEAREST(
LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ffcp-1),
LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD(
LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ffcp-1),
LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_DOWNWARD(
LIBC_NAMESPACE::fputil::cast<float16>(-1.0),
LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_TOWARD_ZERO(
LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ffcp-1),
LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);

// Next float16 value below -0x1.ce4p+1.
x = LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ce8p+1);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_NEAREST(
LIBC_NAMESPACE::fputil::cast<float16>(-1.0),
LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD(
LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ffcp-1),
LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_DOWNWARD(
LIBC_NAMESPACE::fputil::cast<float16>(-1.0),
LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);

EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_TOWARD_ZERO(
LIBC_NAMESPACE::fputil::cast<float16>(-0x1.ffcp-1),
LIBC_NAMESPACE::exp10m1f16(x), FE_INEXACT);
}
25 changes: 25 additions & 0 deletions libc/utils/MPFRWrapper/MPFRUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,29 @@ class MPFRNumber {
return result;
}

MPFRNumber exp10m1() const {
// TODO: Only use mpfr_exp10m1 once CI and buildbots get MPFR >= 4.2.0.
#if MPFR_VERSION_MAJOR > 4 || \
(MPFR_VERSION_MAJOR == 4 && MPFR_VERSION_MINOR >= 2)
MPFRNumber result(*this);
mpfr_exp10m1(result.value, value, mpfr_rounding);
return result;
#else
unsigned int prec = mpfr_precision * 3;
MPFRNumber result(*this, prec);

MPFRNumber ln10(10.0f, prec);
// log(10)
mpfr_log(ln10.value, ln10.value, mpfr_rounding);
// x * log(10)
mpfr_mul(result.value, value, ln10.value, mpfr_rounding);
// e^(x * log(10)) - 1
int ex = mpfr_expm1(result.value, result.value, mpfr_rounding);
mpfr_subnormalize(result.value, ex, mpfr_rounding);
return result;
#endif
}

MPFRNumber expm1() const {
MPFRNumber result(*this);
mpfr_expm1(result.value, value, mpfr_rounding);
Expand Down Expand Up @@ -744,6 +767,8 @@ unary_operation(Operation op, InputType input, unsigned int precision,
return mpfrInput.exp2m1();
case Operation::Exp10:
return mpfrInput.exp10();
case Operation::Exp10m1:
return mpfrInput.exp10m1();
case Operation::Expm1:
return mpfrInput.expm1();
case Operation::Floor:
Expand Down
1 change: 1 addition & 0 deletions libc/utils/MPFRWrapper/MPFRUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ enum class Operation : int {
Exp2,
Exp2m1,
Exp10,
Exp10m1,
Expm1,
Floor,
Log,
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx23Issues.csv
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@
"`LWG3672 <https://wg21.link/LWG3672>`__","``common_iterator::operator->()`` should return by value","2022-07 (Virtual)","|Complete|","19.0",""
"`LWG3683 <https://wg21.link/LWG3683>`__","``operator==`` for ``polymorphic_allocator`` cannot deduce template argument in common cases","2022-07 (Virtual)","|Complete|","20.0",""
"`LWG3687 <https://wg21.link/LWG3687>`__","``expected<cv void, E>`` move constructor should move","2022-07 (Virtual)","|Complete|","16.0",""
"`LWG3692 <https://wg21.link/LWG3692>`__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","2022-07 (Virtual)","","",""
"`LWG3692 <https://wg21.link/LWG3692>`__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","2022-07 (Virtual)","|Complete|","20.0",""
"`LWG3701 <https://wg21.link/LWG3701>`__","Make ``formatter<remove_cvref_t<const charT[N]>, charT>`` requirement explicit","2022-07 (Virtual)","|Complete|","15.0",""
"`LWG3702 <https://wg21.link/LWG3702>`__","Should ``zip_transform_view::iterator`` remove ``operator<``","2022-07 (Virtual)","","",""
"`LWG3703 <https://wg21.link/LWG3703>`__","Missing requirements for ``expected<T, E>`` requires ``is_void<T>``","2022-07 (Virtual)","|Complete|","16.0",""
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx23Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"`P1642R11 <https://wg21.link/P1642R11>`__","Freestanding ``[utilities]``, ``[ranges]``, and ``[iterators]``","2022-07 (Virtual)","","",""
"`P1899R3 <https://wg21.link/P1899R3>`__","``stride_view``","2022-07 (Virtual)","","",""
"`P2093R14 <https://wg21.link/P2093R14>`__","Formatted output","2022-07 (Virtual)","|Complete|","18.0",""
"`P2165R4 <https://wg21.link/P2165R4>`__","Compatibility between ``tuple``, ``pair`` and ``tuple-like`` objects","2022-07 (Virtual)","","",""
"`P2165R4 <https://wg21.link/P2165R4>`__","Compatibility between ``tuple``, ``pair`` and ``tuple-like`` objects","2022-07 (Virtual)","|Partial|","","Only the part for ``zip_view`` is implemented."
"`P2278R4 <https://wg21.link/P2278R4>`__","``cbegin`` should always return a constant iterator","2022-07 (Virtual)","","",""
"`P2286R8 <https://wg21.link/P2286R8>`__","Formatting Ranges","2022-07 (Virtual)","|Complete|","16.0",""
"`P2291R3 <https://wg21.link/P2291R3>`__","Add Constexpr Modifiers to Functions ``to_chars`` and ``from_chars`` for Integral Types in ``<charconv>`` Header","2022-07 (Virtual)","|Complete|","16.0",""
Expand Down
55 changes: 8 additions & 47 deletions libcxx/include/__ranges/zip_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
#include <__utility/forward.h>
#include <__utility/integer_sequence.h>
#include <__utility/move.h>
#include <__utility/pair.h>
#include <tuple>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Expand All @@ -58,22 +57,11 @@ concept __zip_is_common =
(!(bidirectional_range<_Ranges> && ...) && (common_range<_Ranges> && ...)) ||
((random_access_range<_Ranges> && ...) && (sized_range<_Ranges> && ...));

template <typename _Tp, typename _Up>
auto __tuple_or_pair_test() -> pair<_Tp, _Up>;

template <typename... _Types>
requires(sizeof...(_Types) != 2)
auto __tuple_or_pair_test() -> tuple<_Types...>;

template <class... _Types>
using __tuple_or_pair = decltype(__tuple_or_pair_test<_Types...>());

template <class _Fun, class _Tuple>
_LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_transform(_Fun&& __f, _Tuple&& __tuple) {
return std::apply(
[&]<class... _Types>(_Types&&... __elements) {
return __tuple_or_pair<invoke_result_t<_Fun&, _Types>...>(
std::invoke(__f, std::forward<_Types>(__elements))...);
return tuple<invoke_result_t<_Fun&, _Types>...>(std::invoke(__f, std::forward<_Types>(__elements))...);
},
std::forward<_Tuple>(__tuple));
}
Expand All @@ -88,7 +76,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __tuple_for_each(_Fun&& __f, _Tuple&& __tup
}

template <class _Fun, class _Tuple1, class _Tuple2, size_t... _Indices>
_LIBCPP_HIDE_FROM_ABI constexpr __tuple_or_pair<
_LIBCPP_HIDE_FROM_ABI constexpr tuple<
invoke_result_t<_Fun&,
typename tuple_element<_Indices, remove_cvref_t<_Tuple1>>::type,
typename tuple_element<_Indices, remove_cvref_t<_Tuple2>>::type>...>
Expand Down Expand Up @@ -250,10 +238,9 @@ template <input_range... _Views>
requires(view<_Views> && ...) && (sizeof...(_Views) > 0)
template <bool _Const>
class zip_view<_Views...>::__iterator : public __zip_view_iterator_category_base<_Const, _Views...> {
__tuple_or_pair<iterator_t<__maybe_const<_Const, _Views>>...> __current_;
tuple<iterator_t<__maybe_const<_Const, _Views>>...> __current_;

_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(
__tuple_or_pair<iterator_t<__maybe_const<_Const, _Views>>...> __current)
_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(tuple<iterator_t<__maybe_const<_Const, _Views>>...> __current)
: __current_(std::move(__current)) {}

template <bool>
Expand All @@ -266,7 +253,7 @@ class zip_view<_Views...>::__iterator : public __zip_view_iterator_category_base

public:
using iterator_concept = decltype(__get_zip_view_iterator_tag<_Const, _Views...>());
using value_type = __tuple_or_pair<range_value_t<__maybe_const<_Const, _Views>>...>;
using value_type = tuple<range_value_t<__maybe_const<_Const, _Views>>...>;
using difference_type = common_type_t<range_difference_t<__maybe_const<_Const, _Views>>...>;

_LIBCPP_HIDE_FROM_ABI __iterator() = default;
Expand Down Expand Up @@ -340,33 +327,8 @@ class zip_view<_Views...>::__iterator : public __zip_view_iterator_category_base
}
}

_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)
requires __zip_all_random_access<_Const, _Views...>
{
return __x.__current_ < __y.__current_;
}

_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)
requires __zip_all_random_access<_Const, _Views...>
{
return __y < __x;
}

_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)
requires __zip_all_random_access<_Const, _Views...>
{
return !(__y < __x);
}

_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)
requires __zip_all_random_access<_Const, _Views...>
{
return !(__x < __y);
}

_LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)
requires __zip_all_random_access<_Const, _Views...> &&
(three_way_comparable<iterator_t<__maybe_const<_Const, _Views>>> && ...)
requires __zip_all_random_access<_Const, _Views...>
{
return __x.__current_ <=> __y.__current_;
}
Expand Down Expand Up @@ -427,10 +389,9 @@ template <input_range... _Views>
requires(view<_Views> && ...) && (sizeof...(_Views) > 0)
template <bool _Const>
class zip_view<_Views...>::__sentinel {
__tuple_or_pair<sentinel_t<__maybe_const<_Const, _Views>>...> __end_;
tuple<sentinel_t<__maybe_const<_Const, _Views>>...> __end_;

_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(
__tuple_or_pair<sentinel_t<__maybe_const<_Const, _Views>>...> __end)
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(tuple<sentinel_t<__maybe_const<_Const, _Views>>...> __end)
: __end_(__end) {}

friend class zip_view<_Views...>;
Expand Down
3 changes: 0 additions & 3 deletions libcxx/include/__split_buffer
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,6 @@ public:
pointer __end_;
_LIBCPP_COMPRESSED_PAIR(pointer, __end_cap_, allocator_type, __alloc_);

using __alloc_ref = __add_lvalue_reference_t<allocator_type>;
using __alloc_const_ref = __add_lvalue_reference_t<allocator_type>;

__split_buffer(const __split_buffer&) = delete;
__split_buffer& operator=(const __split_buffer&) = delete;

Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/future
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ public:
_LIBCPP_HIDE_FROM_ABI void set_value_at_thread_exit(_Arg&& __arg);

_LIBCPP_HIDE_FROM_ABI _Rp move();
_LIBCPP_HIDE_FROM_ABI __add_lvalue_reference_t<_Rp> copy();
_LIBCPP_HIDE_FROM_ABI _Rp& copy();
};

template <class _Rp>
Expand Down Expand Up @@ -636,7 +636,7 @@ _Rp __assoc_state<_Rp>::move() {
}

template <class _Rp>
__add_lvalue_reference_t<_Rp> __assoc_state<_Rp>::copy() {
_Rp& __assoc_state<_Rp>::copy() {
unique_lock<mutex> __lk(this->__mut_);
this->__sub_wait(__lk);
if (this->__exception_ != nullptr)
Expand Down
4 changes: 0 additions & 4 deletions libcxx/test/std/ranges/range.adaptors/range.zip/cpo.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,7 @@ constexpr bool test() {
std::ranges::zip_view<std::ranges::zip_view<SizedRandomAccessView, SizedRandomAccessView>>> decltype(auto) v2 =
std::views::zip(v);

#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
static_assert(std::is_same_v<std::ranges::range_reference_t<decltype(v2)>, std::tuple<std::pair<int&, int&>>>);
#else
static_assert(std::is_same_v<std::ranges::range_reference_t<decltype(v2)>, std::tuple<std::tuple<int&, int&>>>);
#endif
}
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,8 @@ constexpr bool test() {
using View = std::ranges::zip_view<DefaultConstructibleView, DefaultConstructibleView>;
View v = View(); // the default constructor is not explicit
assert(v.size() == 3);
auto it = v.begin();
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
using Value = std::pair<const int&, const int&>;
#else
auto it = v.begin();
using Value = std::tuple<const int&, const int&>;
#endif
assert(*it++ == Value(buff[0], buff[0]));
assert(*it++ == Value(buff[1], buff[1]));
assert(*it == Value(buff[2], buff[2]));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,8 @@

// friend constexpr bool operator==(const iterator& x, const iterator& y)
// requires (equality_comparable<iterator_t<maybe-const<Const, Views>>> && ...);
// friend constexpr bool operator<(const iterator& x, const iterator& y)
// requires all-random-access<Const, Views...>;
// friend constexpr bool operator>(const iterator& x, const iterator& y)
// requires all-random-access<Const, Views...>;
// friend constexpr bool operator<=(const iterator& x, const iterator& y)
// requires all-random-access<Const, Views...>;
// friend constexpr bool operator>=(const iterator& x, const iterator& y)
// requires all-random-access<Const, Views...>;
// friend constexpr auto operator<=>(const iterator& x, const iterator& y)
// requires all-random-access<Const, Views...> &&
// (three_way_comparable<iterator_t<maybe-const<Const, Views>>> && ...);
// requires all-random-access<Const, Views...>;

#include <ranges>
#include <compare>
Expand Down Expand Up @@ -165,12 +156,7 @@ constexpr bool test() {
using Subrange = std::ranges::subrange<It>;
static_assert(!std::three_way_comparable<It>);
using R = std::ranges::zip_view<Subrange, Subrange>;
#ifdef _LIBCPP_VERSION
// libc++ hasn't implemented LWG-3692 "zip_view::iterator's operator<=> is overconstrained"
static_assert(!std::three_way_comparable<std::ranges::iterator_t<R>>);
#else
static_assert(std::three_way_comparable<std::ranges::iterator_t<R>>);
#endif

int a[] = {1, 2, 3, 4};
int b[] = {5, 6, 7, 8, 9};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,7 @@ constexpr bool test() {
auto [x, y] = *it;
assert(&x == &(a[0]));
assert(&y == &(b[0]));
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
static_assert(std::is_same_v<decltype(*it), std::pair<int&, double&>>);
#else
static_assert(std::is_same_v<decltype(*it), std::tuple<int&, double&>>);
#endif

x = 5;
y = 0.1;
Expand All @@ -70,11 +66,7 @@ constexpr bool test() {
auto it = v.begin();
assert(&(std::get<0>(*it)) == &(a[0]));
assert(&(std::get<1>(*it)) == &(a[0]));
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
static_assert(std::is_same_v<decltype(*it), std::pair<int&, int const&>>);
#else
static_assert(std::is_same_v<decltype(*it), std::tuple<int&, int const&>>);
#endif
}
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,15 @@ struct ConstVeryDifferentRange {
void test() {
int buffer[] = {1, 2, 3, 4};
{
// 2 views should have pair value_type
// 2 views should have 2-tuple value_type
// random_access_iterator_tag
std::ranges::zip_view v(buffer, buffer);
using Iter = decltype(v.begin());

static_assert(std::is_same_v<Iter::iterator_concept, std::random_access_iterator_tag>);
static_assert(std::is_same_v<Iter::iterator_category, std::input_iterator_tag>);
static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>);
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
static_assert(std::is_same_v<Iter::value_type, std::pair<int, int>>);
#else
static_assert(std::is_same_v<Iter::value_type, std::tuple<int, int>>);
#endif
static_assert(HasIterCategory<Iter>);
}

Expand Down Expand Up @@ -124,11 +120,7 @@ void test() {
static_assert(std::is_same_v<Iter::iterator_concept, std::random_access_iterator_tag>);
static_assert(std::is_same_v<Iter::iterator_category, std::input_iterator_tag>);
static_assert(std::is_same_v<Iter::difference_type, std::ptrdiff_t>);
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
static_assert(std::is_same_v<Iter::value_type, std::pair<int, std::pair<int, int>>>);
#else
static_assert(std::is_same_v<Iter::value_type, std::tuple<int, std::tuple<int, int>>>);
#endif
static_assert(HasIterCategory<Iter>);
}

Expand Down Expand Up @@ -169,11 +161,7 @@ void test() {
// value_type of multiple views with different value_type
std::ranges::zip_view v{foos, bars};
using Iter = decltype(v.begin());
#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
static_assert(std::is_same_v<Iter::value_type, std::pair<Foo, Bar>>);
#else
static_assert(std::is_same_v<Iter::value_type, std::tuple<Foo, Bar>>);
#endif
}

{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,7 @@ constexpr bool test() {
assert(it[2] == *(it + 2));
assert(it[4] == *(it + 4));

#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
static_assert(std::is_same_v<decltype(it[2]), std::pair<int&, int>>);
#else
static_assert(std::is_same_v<decltype(it[2]), std::tuple<int&, int>>);
#endif
}

{
Expand All @@ -42,11 +38,7 @@ constexpr bool test() {
assert(it[2] == *(it + 2));
assert(it[4] == *(it + 4));

#ifdef _LIBCPP_VERSION // libc++ doesn't implement P2165R4 yet
static_assert(std::is_same_v<decltype(it[2]), std::pair<int&, int&>>);
#else
static_assert(std::is_same_v<decltype(it[2]), std::tuple<int&, int&>>);
#endif
}

{
Expand Down
8 changes: 4 additions & 4 deletions lld/ELF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1703,7 +1703,7 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
parallel::strategy = hardware_concurrency(threads);
ctx.arg.thinLTOJobs = v;
} else if (parallel::strategy.compute_thread_count() > 16) {
log("set maximum concurrency to 16, specify --threads= to change");
Log(ctx) << "set maximum concurrency to 16, specify --threads= to change";
parallel::strategy = hardware_concurrency(16);
}
if (auto *arg = args.getLastArg(OPT_thinlto_jobs_eq))
Expand Down Expand Up @@ -2481,7 +2481,7 @@ static void readSymbolPartitionSection(Ctx &ctx, InputSectionBase *s) {
StringRef partName = reinterpret_cast<const char *>(s->content().data());
for (Partition &part : ctx.partitions) {
if (part.name == partName) {
sym->partition = part.getNumber();
sym->partition = part.getNumber(ctx);
return;
}
}
Expand All @@ -2505,12 +2505,12 @@ static void readSymbolPartitionSection(Ctx &ctx, InputSectionBase *s) {
// sizes of the Partition fields in InputSectionBase and Symbol, as well as
// the amount of space devoted to the partition number in RankFlags.
if (ctx.partitions.size() == 254)
fatal("may not have more than 254 partitions");
Fatal(ctx) << "may not have more than 254 partitions";

ctx.partitions.emplace_back(ctx);
Partition &newPart = ctx.partitions.back();
newPart.name = partName;
sym->partition = newPart.getNumber();
sym->partition = newPart.getNumber(ctx);
}

static void markBuffersAsDontNeed(Ctx &ctx, bool skipLinkedOutput) {
Expand Down
2 changes: 1 addition & 1 deletion lld/ELF/InputSection.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class SectionBase {
// The 1-indexed partition that this section is assigned to by the garbage
// collector, or 0 if this section is dead. Normally there is only one
// partition, so this will either be 0 or 1.
elf::Partition &getPartition() const;
elf::Partition &getPartition(Ctx &) const;

// These corresponds to the fields in Elf_Shdr.
uint64_t flags;
Expand Down
4 changes: 2 additions & 2 deletions lld/ELF/Relocations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,7 @@ template <bool shard = false>
static void addRelativeReloc(Ctx &ctx, InputSectionBase &isec,
uint64_t offsetInSec, Symbol &sym, int64_t addend,
RelExpr expr, RelType type) {
Partition &part = isec.getPartition();
Partition &part = isec.getPartition(ctx);

if (sym.isTagged()) {
std::lock_guard<std::mutex> lock(relocMutex);
Expand Down Expand Up @@ -1159,7 +1159,7 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
if (ctx.arg.emachine == EM_MIPS && rel == ctx.target->symbolicRel)
rel = ctx.target->relativeRel;
std::lock_guard<std::mutex> lock(relocMutex);
Partition &part = sec->getPartition();
Partition &part = sec->getPartition(ctx);
if (ctx.arg.emachine == EM_AARCH64 && type == R_AARCH64_AUTH_ABS64) {
// For a preemptible symbol, we can't use a relative relocation. For an
// undefined symbol, we can't compute offset at link-time and use a
Expand Down
2 changes: 1 addition & 1 deletion lld/ELF/SymbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ void SymbolTable::scanVersionScript() {
globalAsteriskFound = !isLocal;
}
}
assignWildcard(pat, isLocal ? VER_NDX_LOCAL : ver->id, ver->name);
assignWildcard(pat, isLocal ? (uint16_t)VER_NDX_LOCAL : ver->id, ver->name);
};
for (VersionDefinition &v : llvm::reverse(ctx.arg.versionDefinitions)) {
for (SymbolVersion &pat : v.nonLocalPatterns)
Expand Down
78 changes: 39 additions & 39 deletions lld/ELF/SyntheticSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ SmallVector<EhFrameSection::FdeData, 0> EhFrameSection::getFdeData() const {
uint8_t *buf = ctx.bufferStart + getParent()->offset + outSecOff;
SmallVector<FdeData, 0> ret;

uint64_t va = getPartition().ehFrameHdr->getVA();
uint64_t va = getPartition(ctx).ehFrameHdr->getVA();
for (CieRecord *rec : cieRecords) {
uint8_t enc = getFdeEncoding(rec->cie);
for (EhSectionPiece *fde : rec->fdes) {
Expand Down Expand Up @@ -650,8 +650,8 @@ void EhFrameSection::writeTo(uint8_t *buf) {
for (EhInputSection *s : sections)
ctx.target->relocateAlloc(*s, buf);

if (getPartition().ehFrameHdr && getPartition().ehFrameHdr->getParent())
getPartition().ehFrameHdr->write();
if (getPartition(ctx).ehFrameHdr && getPartition(ctx).ehFrameHdr->getParent())
getPartition(ctx).ehFrameHdr->write();
}

GotSection::GotSection(Ctx &ctx)
Expand Down Expand Up @@ -1325,7 +1325,7 @@ static uint64_t addPltRelSz(Ctx &ctx) { return ctx.in.relaPlt->getSize(); }
template <class ELFT>
std::vector<std::pair<int32_t, uint64_t>>
DynamicSection<ELFT>::computeContents() {
elf::Partition &part = getPartition();
elf::Partition &part = getPartition(ctx);
bool isMain = part.name.empty();
std::vector<std::pair<int32_t, uint64_t>> entries;

Expand Down Expand Up @@ -1586,7 +1586,7 @@ DynamicSection<ELFT>::computeContents() {
}

template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
if (OutputSection *sec = getPartition().dynStrTab->getParent())
if (OutputSection *sec = getPartition(ctx).dynStrTab->getParent())
getParent()->link = sec->sectionIndex;
this->size = computeContents().size() * this->entsize;
}
Expand Down Expand Up @@ -1688,7 +1688,7 @@ void RelocationBaseSection::partitionRels() {
}

void RelocationBaseSection::finalizeContents() {
SymbolTableBaseSection *symTab = getPartition().dynSymTab.get();
SymbolTableBaseSection *symTab = getPartition(ctx).dynSymTab.get();

// When linking glibc statically, .rel{,a}.plt contains R_*_IRELATIVE
// relocations due to IFUNC (e.g. strcpy). sh_link will be set to 0 in that
Expand All @@ -1712,7 +1712,7 @@ void DynamicReloc::computeRaw(Ctx &ctx, SymbolTableBaseSection *symt) {
}

void RelocationBaseSection::computeRels() {
SymbolTableBaseSection *symTab = getPartition().dynSymTab.get();
SymbolTableBaseSection *symTab = getPartition(ctx).dynSymTab.get();
parallelForEach(relocs, [&ctx = ctx, symTab](DynamicReloc &rel) {
rel.computeRaw(ctx, symTab);
});
Expand Down Expand Up @@ -1852,7 +1852,7 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize(Ctx &ctx) {
for (const DynamicReloc &rel : relocs) {
Elf_Rela r;
r.r_offset = rel.getOffset();
r.setSymbolAndType(rel.getSymIndex(getPartition().dynSymTab.get()),
r.setSymbolAndType(rel.getSymIndex(getPartition(ctx).dynSymTab.get()),
rel.type, false);
r.r_addend = ctx.arg.isRela ? rel.computeAddend(ctx) : 0;

Expand Down Expand Up @@ -2162,9 +2162,9 @@ void SymbolTableBaseSection::finalizeContents() {
// Because the first symbol entry is a null entry, 1 is the first.
getParent()->info = 1;

if (getPartition().gnuHashTab) {
if (getPartition(ctx).gnuHashTab) {
// NB: It also sorts Symbols to meet the GNU hash table requirements.
getPartition().gnuHashTab->addSymbols(symbols);
getPartition(ctx).gnuHashTab->addSymbols(symbols);
} else if (ctx.arg.emachine == EM_MIPS) {
sortMipsSymbols(ctx, symbols);
}
Expand Down Expand Up @@ -2416,7 +2416,7 @@ GnuHashTableSection::GnuHashTableSection(Ctx &ctx)
".gnu.hash") {}

void GnuHashTableSection::finalizeContents() {
if (OutputSection *sec = getPartition().dynSymTab->getParent())
if (OutputSection *sec = getPartition(ctx).dynSymTab->getParent())
getParent()->link = sec->sectionIndex;

// Computes bloom filter size in word size. We want to allocate 12
Expand All @@ -2438,7 +2438,7 @@ void GnuHashTableSection::writeTo(uint8_t *buf) {
// Write a header.
write32(ctx, buf, nBuckets);
write32(ctx, buf + 4,
getPartition().dynSymTab->getNumSymbols() - symbols.size());
getPartition(ctx).dynSymTab->getNumSymbols() - symbols.size());
write32(ctx, buf + 8, maskWords);
write32(ctx, buf + 12, Shift2);
buf += 16;
Expand Down Expand Up @@ -2474,7 +2474,7 @@ void GnuHashTableSection::writeTo(uint8_t *buf) {
// Write a hash bucket. Hash buckets contain indices in the following hash
// value table.
write32(ctx, buckets + i->bucketIdx,
getPartition().dynSymTab->getSymbolIndex(*i->sym));
getPartition(ctx).dynSymTab->getSymbolIndex(*i->sym));
oldBucket = i->bucketIdx;
}
}
Expand Down Expand Up @@ -2527,7 +2527,7 @@ HashTableSection::HashTableSection(Ctx &ctx)
}

void HashTableSection::finalizeContents() {
SymbolTableBaseSection *symTab = getPartition().dynSymTab.get();
SymbolTableBaseSection *symTab = getPartition(ctx).dynSymTab.get();

if (OutputSection *sec = symTab->getParent())
getParent()->link = sec->sectionIndex;
Expand All @@ -2541,7 +2541,7 @@ void HashTableSection::finalizeContents() {
}

void HashTableSection::writeTo(uint8_t *buf) {
SymbolTableBaseSection *symTab = getPartition().dynSymTab.get();
SymbolTableBaseSection *symTab = getPartition(ctx).dynSymTab.get();
unsigned numSymbols = symTab->getNumSymbols();

uint32_t *p = reinterpret_cast<uint32_t *>(buf);
Expand Down Expand Up @@ -3667,14 +3667,14 @@ void EhFrameHeader::writeTo(uint8_t *buf) {
void EhFrameHeader::write() {
uint8_t *buf = ctx.bufferStart + getParent()->offset + outSecOff;
using FdeData = EhFrameSection::FdeData;
SmallVector<FdeData, 0> fdes = getPartition().ehFrame->getFdeData();
SmallVector<FdeData, 0> fdes = getPartition(ctx).ehFrame->getFdeData();

buf[0] = 1;
buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4;
buf[2] = DW_EH_PE_udata4;
buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4;
write32(ctx, buf + 4,
getPartition().ehFrame->getParent()->addr - this->getVA() - 4);
getPartition(ctx).ehFrame->getParent()->addr - this->getVA() - 4);
write32(ctx, buf + 8, fdes.size());
buf += 12;

Expand All @@ -3687,31 +3687,31 @@ void EhFrameHeader::write() {

size_t EhFrameHeader::getSize() const {
// .eh_frame_hdr has a 12 bytes header followed by an array of FDEs.
return 12 + getPartition().ehFrame->numFdes * 8;
return 12 + getPartition(ctx).ehFrame->numFdes * 8;
}

bool EhFrameHeader::isNeeded() const {
return isLive() && getPartition().ehFrame->isNeeded();
return isLive() && getPartition(ctx).ehFrame->isNeeded();
}

VersionDefinitionSection::VersionDefinitionSection(Ctx &ctx)
: SyntheticSection(ctx, SHF_ALLOC, SHT_GNU_verdef, sizeof(uint32_t),
".gnu.version_d") {}

StringRef VersionDefinitionSection::getFileDefName() {
if (!getPartition().name.empty())
return getPartition().name;
if (!getPartition(ctx).name.empty())
return getPartition(ctx).name;
if (!ctx.arg.soName.empty())
return ctx.arg.soName;
return ctx.arg.outputFile;
}

void VersionDefinitionSection::finalizeContents() {
fileDefNameOff = getPartition().dynStrTab->addString(getFileDefName());
fileDefNameOff = getPartition(ctx).dynStrTab->addString(getFileDefName());
for (const VersionDefinition &v : namedVersionDefs(ctx))
verDefNameOffs.push_back(getPartition().dynStrTab->addString(v.name));
verDefNameOffs.push_back(getPartition(ctx).dynStrTab->addString(v.name));

if (OutputSection *sec = getPartition().dynStrTab->getParent())
if (OutputSection *sec = getPartition(ctx).dynStrTab->getParent())
getParent()->link = sec->sectionIndex;

// sh_info should be set to the number of definitions. This fact is missed in
Expand Down Expand Up @@ -3765,16 +3765,16 @@ VersionTableSection::VersionTableSection(Ctx &ctx)
void VersionTableSection::finalizeContents() {
// At the moment of june 2016 GNU docs does not mention that sh_link field
// should be set, but Sun docs do. Also readelf relies on this field.
getParent()->link = getPartition().dynSymTab->getParent()->sectionIndex;
getParent()->link = getPartition(ctx).dynSymTab->getParent()->sectionIndex;
}

size_t VersionTableSection::getSize() const {
return (getPartition().dynSymTab->getSymbols().size() + 1) * 2;
return (getPartition(ctx).dynSymTab->getSymbols().size() + 1) * 2;
}

void VersionTableSection::writeTo(uint8_t *buf) {
buf += 2;
for (const SymbolTableEntry &s : getPartition().dynSymTab->getSymbols()) {
for (const SymbolTableEntry &s : getPartition(ctx).dynSymTab->getSymbols()) {
// For an unextracted lazy symbol (undefined weak), it must have been
// converted to Undefined and have VER_NDX_GLOBAL version here.
assert(!s.sym->isLazy());
Expand All @@ -3785,7 +3785,7 @@ void VersionTableSection::writeTo(uint8_t *buf) {

bool VersionTableSection::isNeeded() const {
return isLive() &&
(getPartition().verDef || getPartition().verNeed->isNeeded());
(getPartition(ctx).verDef || getPartition(ctx).verNeed->isNeeded());
}

void elf::addVerneed(Ctx &ctx, Symbol &ss) {
Expand Down Expand Up @@ -3817,7 +3817,7 @@ template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() {
continue;
verneeds.emplace_back();
Verneed &vn = verneeds.back();
vn.nameStrTab = getPartition().dynStrTab->addString(f->soName);
vn.nameStrTab = getPartition(ctx).dynStrTab->addString(f->soName);
bool isLibc = ctx.arg.relrGlibc && f->soName.starts_with("libc.so.");
bool isGlibc2 = false;
for (unsigned i = 0; i != f->vernauxs.size(); ++i) {
Expand All @@ -3829,17 +3829,17 @@ template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() {
if (isLibc && ver.starts_with("GLIBC_2."))
isGlibc2 = true;
vn.vernauxs.push_back({verdef->vd_hash, f->vernauxs[i],
getPartition().dynStrTab->addString(ver)});
getPartition(ctx).dynStrTab->addString(ver)});
}
if (isGlibc2) {
const char *ver = "GLIBC_ABI_DT_RELR";
vn.vernauxs.push_back({hashSysV(ver),
++SharedFile::vernauxNum + getVerDefNum(ctx),
getPartition().dynStrTab->addString(ver)});
getPartition(ctx).dynStrTab->addString(ver)});
}
}

if (OutputSection *sec = getPartition().dynStrTab->getParent())
if (OutputSection *sec = getPartition(ctx).dynStrTab->getParent())
getParent()->link = sec->sectionIndex;
getParent()->info = verneeds.size();
}
Expand Down Expand Up @@ -3995,7 +3995,7 @@ template <class ELFT> void elf::splitSections(Ctx &ctx) {
void elf::combineEhSections(Ctx &ctx) {
llvm::TimeTraceScope timeScope("Combine EH sections");
for (EhInputSection *sec : ctx.ehInputSections) {
EhFrameSection &eh = *sec->getPartition().ehFrame;
EhFrameSection &eh = *sec->getPartition(ctx).ehFrame;
sec->parent = &eh;
eh.addralign = std::max(eh.addralign, sec->addralign);
eh.sections.push_back(sec);
Expand All @@ -4004,12 +4004,12 @@ void elf::combineEhSections(Ctx &ctx) {

if (!ctx.mainPart->armExidx)
return;
llvm::erase_if(ctx.inputSections, [](InputSectionBase *s) {
llvm::erase_if(ctx.inputSections, [&](InputSectionBase *s) {
// Ignore dead sections and the partition end marker (.part.end),
// whose partition number is out of bounds.
if (!s->isLive() || s->partition == 255)
return false;
Partition &part = s->getPartition();
Partition &part = s->getPartition(ctx);
return s->kind() == SectionBase::Regular && part.armExidx &&
part.armExidx->addSection(cast<InputSection>(s));
});
Expand Down Expand Up @@ -4447,7 +4447,7 @@ size_t PartitionElfHeaderSection<ELFT>::getSize() const {

template <typename ELFT>
void PartitionElfHeaderSection<ELFT>::writeTo(uint8_t *buf) {
writeEhdr<ELFT>(ctx, buf, getPartition());
writeEhdr<ELFT>(ctx, buf, getPartition(ctx));

// Loadable partitions are always ET_DYN.
auto *eHdr = reinterpret_cast<typename ELFT::Ehdr *>(buf);
Expand All @@ -4460,12 +4460,12 @@ PartitionProgramHeadersSection<ELFT>::PartitionProgramHeadersSection(Ctx &ctx)

template <typename ELFT>
size_t PartitionProgramHeadersSection<ELFT>::getSize() const {
return sizeof(typename ELFT::Phdr) * getPartition().phdrs.size();
return sizeof(typename ELFT::Phdr) * getPartition(ctx).phdrs.size();
}

template <typename ELFT>
void PartitionProgramHeadersSection<ELFT>::writeTo(uint8_t *buf) {
writePhdrs<ELFT>(buf, getPartition());
writePhdrs<ELFT>(buf, getPartition(ctx));
}

PartitionIndexSection::PartitionIndexSection(Ctx &ctx)
Expand Down Expand Up @@ -4747,7 +4747,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) {
const unsigned threadCount = ctx.arg.threadCount;
for (Partition &part : ctx.partitions) {
auto add = [&](SyntheticSection &sec) {
sec.partition = part.getNumber();
sec.partition = part.getNumber(ctx);
ctx.inputSections.push_back(&sec);
};

Expand Down
4 changes: 2 additions & 2 deletions lld/ELF/SyntheticSections.h
Original file line number Diff line number Diff line change
Expand Up @@ -1475,10 +1475,10 @@ struct Partition {
std::unique_ptr<VersionTableSection> verSym;

Partition(Ctx &ctx) : ctx(ctx) {}
unsigned getNumber() const { return this - &ctx.partitions[0] + 1; }
unsigned getNumber(Ctx &ctx) const { return this - &ctx.partitions[0] + 1; }
};

inline Partition &SectionBase::getPartition() const {
inline Partition &SectionBase::getPartition(Ctx &ctx) const {
assert(isLive());
return ctx.partitions[partition - 1];
}
Expand Down
2 changes: 1 addition & 1 deletion lld/ELF/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ std::string lld::toString(RelType type) {
const ELFSyncStream &elf::operator<<(const ELFSyncStream &s, RelType type) {
StringRef buf = getELFRelocationTypeName(s.ctx.arg.emachine, type);
if (buf == "Unknown")
s << ("Unknown (" + Twine(type) + ")").str();
s << "Unknown (" << Twine(type) << ")";
else
s << buf;
return s;
Expand Down
4 changes: 2 additions & 2 deletions lld/ELF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2191,7 +2191,7 @@ SmallVector<PhdrEntry *, 0> Writer<ELFT>::createPhdrs(Partition &part) {
return ret.back();
};

unsigned partNo = part.getNumber();
unsigned partNo = part.getNumber(ctx);
bool isMain = partNo == 1;

// Add the first PT_LOAD segment for regular output sections.
Expand Down Expand Up @@ -2381,7 +2381,7 @@ SmallVector<PhdrEntry *, 0> Writer<ELFT>::createPhdrs(Partition &part) {
template <class ELFT>
void Writer<ELFT>::addPhdrForSection(Partition &part, unsigned shType,
unsigned pType, unsigned pFlags) {
unsigned partNo = part.getNumber();
unsigned partNo = part.getNumber(ctx);
auto i = llvm::find_if(ctx.outputSections, [=](OutputSection *cmd) {
return cmd->partition == partNo && cmd->type == shType;
});
Expand Down
5 changes: 3 additions & 2 deletions lldb/source/Core/Progress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,11 @@ void ProgressManager::Decrement(const Progress::ProgressData &progress_data) {
std::lock_guard<std::mutex> lock(m_entries_mutex);
llvm::StringRef key = progress_data.title;

if (!m_entries.contains(key))
auto it = m_entries.find(key);
if (it == m_entries.end())
return;

Entry &entry = m_entries[key];
Entry &entry = it->second;
entry.refcount--;

if (entry.refcount == 0) {
Expand Down
56 changes: 39 additions & 17 deletions lldb/source/Utility/DiagnosticsRendering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,7 @@ void RenderDiagnosticDetails(Stream &stream,
spacer = "";
}

// Print a line with caret indicator(s) below the lldb prompt + command.
const size_t padding = *offset_in_command;
stream << std::string(padding, ' ');

size_t offset = 1;
// Partition the diagnostics.
std::vector<DiagnosticDetail> remaining_details, other_details,
hidden_details;
for (const DiagnosticDetail &detail : details) {
Expand All @@ -98,14 +94,39 @@ void RenderDiagnosticDetails(Stream &stream,
continue;
}

auto &loc = *detail.source_location;
remaining_details.push_back(detail);
if (offset > loc.column)
continue;
stream << std::string(loc.column - offset, ' ') << cursor;
for (unsigned i = 0; i + 1 < loc.length; ++i)
stream << underline;
offset = loc.column + 1;
}

// Sort the diagnostics.
auto sort = [](auto &ds) {
llvm::sort(ds.begin(), ds.end(), [](auto &d1, auto &d2) {
auto l1 = d1.source_location.value_or(DiagnosticDetail::SourceLocation{});
auto l2 = d2.source_location.value_or(DiagnosticDetail::SourceLocation{});
return std::pair(l1.line, l2.column) < std::pair(l1.line, l2.column);
});
};
sort(remaining_details);
sort(other_details);
sort(hidden_details);

// Print a line with caret indicator(s) below the lldb prompt + command.
const size_t padding = *offset_in_command;
stream << std::string(padding, ' ');
{
size_t x_pos = 1;
for (const DiagnosticDetail &detail : remaining_details) {
auto &loc = *detail.source_location;

if (x_pos > loc.column)
continue;

stream << std::string(loc.column - x_pos, ' ') << cursor;
++x_pos;
for (unsigned i = 0; i + 1 < loc.length; ++i) {
stream << underline;
++x_pos;
}
}
}
stream << '\n';

Expand All @@ -117,18 +138,19 @@ void RenderDiagnosticDetails(Stream &stream,
// Get the information to print this detail and remove it from the stack.
// Print all the lines for all the other messages first.
stream << std::string(padding, ' ');
size_t offset = 1;
size_t x_pos = 1;
for (auto &remaining_detail :
llvm::ArrayRef(remaining_details).drop_back(1)) {
uint16_t column = remaining_detail.source_location->column;
stream << std::string(column - offset, ' ') << vbar;
offset = column + 1;
if (x_pos <= column)
stream << std::string(column - x_pos, ' ') << vbar;
x_pos = column + 1;
}

// Print the line connecting the ^ with the error message.
uint16_t column = detail->source_location->column;
if (offset <= column)
stream << std::string(column - offset, ' ') << joint << hbar << spacer;
if (x_pos <= column)
stream << std::string(column - x_pos, ' ') << joint << hbar << spacer;

// Print a colorized string based on the message's severity type.
PrintSeverity(stream, detail->severity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
class TestCase(TestBase):
@add_test_categories(["libc++"])
@skipIf(compiler=no_match("clang"))
@skipIfLinux # https://discourse.llvm.org/t/lldb-test-failures-on-linux/80095
def test(self):
self.build()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class TestDbgInfoContentVector(TestBase):
@skipIf(compiler="clang", compiler_version=["<", "12.0"])
@skipIf(macos_version=["<", "14.0"])
@skipIfDarwin # https://github.com/llvm/llvm-project/issues/106475
@skipIfLinux # https://discourse.llvm.org/t/lldb-test-failures-on-linux/80095
def test(self):
self.build()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
class TestVectorOfVectors(TestBase):
@add_test_categories(["libc++"])
@skipIf(compiler=no_match("clang"))
@skipIfLinux # https://discourse.llvm.org/t/lldb-test-failures-on-linux/80095
def test(self):
self.build()

Expand Down
2 changes: 1 addition & 1 deletion lldb/test/API/commands/expression/top-level/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ all: dummy
include Makefile.rules

dummy: dummy.cpp
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
CXX_SOURCES=dummy.cpp EXE=dummy

4 changes: 2 additions & 2 deletions lldb/test/API/commands/expression/weak_symbols/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ a.out: libdylib.dylib
include Makefile.rules

libdylib.dylib: dylib.c
$(MAKE) -C $(BUILDDIR) -f $(MAKEFILE_RULES) \
"$(MAKE)" -C $(BUILDDIR) -f $(MAKEFILE_RULES) \
C_SOURCES= DYLIB_C_SOURCES=dylib.c DYLIB_NAME=dylib \
CFLAGS_EXTRAS=-DHAS_THEM LD_EXTRAS=-dynamiclib

hidden/libdylib.dylib:
mkdir hidden
$(MAKE) -C $(BUILDDIR)/hidden -f $(MAKEFILE_RULES) \
"$(MAKE)" -C $(BUILDDIR)/hidden -f $(MAKEFILE_RULES) \
C_SOURCES= DYLIB_C_SOURCES=dylib.c DYLIB_NAME=dylib \
LD_EXTRAS=-dynamiclib
2 changes: 1 addition & 1 deletion lldb/test/API/commands/target/create-deps/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ a.out: libload_a
include Makefile.rules

libload_a:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=load_a DYLIB_CXX_SOURCES=a.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ CXX_SOURCES := main.cpp
USE_LIBDL := 1

lib_b:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=lib_b
all: lib_b

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ C_SOURCES := main.c
USE_LIBDL := 1

other:
$(MAKE) -f $(MAKEFILE_RULES) C_SOURCES=other.c EXE=other
"$(MAKE)" -f $(MAKEFILE_RULES) C_SOURCES=other.c EXE=other
all: other

include Makefile.rules
2 changes: 1 addition & 1 deletion lldb/test/API/functionalities/exec/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ all: secondprog
include Makefile.rules

secondprog: secondprog.cpp
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
CXX_SOURCES=secondprog.cpp EXE=secondprog
2 changes: 1 addition & 1 deletion lldb/test/API/functionalities/jitloader_gdb/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ all: a.out simple
include Makefile.rules

simple:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
C_SOURCES=simple.c EXE=simple
4 changes: 2 additions & 2 deletions lldb/test/API/functionalities/limit-debug-info/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ include Makefile.rules
a.out: libone libtwo

libone:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=one.cpp DYLIB_NAME=one \
CFLAGS_EXTRAS="$(ONE_CXXFLAGS)"

libtwo: libone
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=two.cpp DYLIB_NAME=two \
CFLAGS_EXTRAS="$(TWO_CXXFLAGS)" LD_EXTRAS="-L. -lone"
2 changes: 1 addition & 1 deletion lldb/test/API/functionalities/load_after_attach/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ CXX_SOURCES := main.cpp
USE_LIBDL := 1

lib_b:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=lib_b
all: lib_b

Expand Down
6 changes: 3 additions & 3 deletions lldb/test/API/functionalities/load_lazy/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ else
endif

t1: t2_0
$(MAKE) VPATH=$(SRCDIR) -f $(MAKEFILE_RULES) \
"$(MAKE)" VPATH=$(SRCDIR) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_C_SOURCES=t1.c DYLIB_NAME=t1 LD_EXTRAS="-L. $(LINKFLAGS)"

t2_0:
$(MAKE) VPATH=$(SRCDIR) -f $(MAKEFILE_RULES) \
"$(MAKE)" VPATH=$(SRCDIR) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_C_SOURCES=t2_0.c DYLIB_NAME=t2_0

t2_1:
$(MAKE) VPATH=$(SRCDIR) -f $(MAKEFILE_RULES) \
"$(MAKE)" VPATH=$(SRCDIR) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_C_SOURCES=t2_1.c DYLIB_NAME=t2_1
10 changes: 5 additions & 5 deletions lldb/test/API/functionalities/load_unload/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,25 @@ a.out: lib_b lib_a lib_c lib_d hidden_lib_d
include Makefile.rules

lib_a: lib_b
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=a.cpp DYLIB_NAME=loadunload_a \
LD_EXTRAS="-L. -lloadunload_b"

lib_b:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=loadunload_b

lib_c:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=c.cpp DYLIB_NAME=loadunload_c

lib_d:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=loadunload_d
ifeq ($(OS),Darwin)
install_name_tool -id @executable_path/libloadunload_d.dylib libloadunload_d.dylib
endif

hidden_lib_d: hidden
$(MAKE) VPATH=$(SRCDIR)/hidden -C hidden -f $(MAKEFILE_RULES) \
"$(MAKE)" VPATH=$(SRCDIR)/hidden -C hidden -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=loadunload_d
2 changes: 1 addition & 1 deletion lldb/test/API/functionalities/load_using_paths/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ all: hidden_lib a.out
include Makefile.rules

hidden_lib:
$(MAKE) VPATH=$(SRCDIR)/hidden -C hidden -f $(MAKEFILE_RULES) \
"$(MAKE)" VPATH=$(SRCDIR)/hidden -C hidden -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=loadunload

2 changes: 1 addition & 1 deletion lldb/test/API/functionalities/scripted_process/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ CXXFLAGS_EXTRAS := -target $(TRIPLE)
all: libbaz.dylib a.out

libbaz.dylib: baz.cpp
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=baz DYLIB_CXX_SOURCES=baz.cpp

include Makefile.rules
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ a.out: lib_a lib_b
include Makefile.rules

lib_a:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=a.cpp DYLIB_NAME=load_a

lib_b:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=load_b


Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ a.out: lib_One lib_Two
lib_One: lib_Two

lib_%:
$(MAKE) VPATH=$(SRCDIR)/$* -I $(SRCDIR) -f $(SRCDIR)/$*.mk DSYMUTIL=$(DSYMUTIL)
"$(MAKE)" VPATH=$(SRCDIR)/$* -I $(SRCDIR) -f $(SRCDIR)/$*.mk DSYMUTIL=$(DSYMUTIL)
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
CXX_SOURCES := main.cpp
LD_EXTRAS := -L. -l_d -l_c -l_a -l_b
LD_EXTRAS := -L. -l_d -l_c -l_a -l_b

a.out: lib_b lib_a lib_c lib_d

include Makefile.rules

lib_a: lib_b
$(MAKE) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=a.cpp DYLIB_NAME=_a \
LD_EXTRAS="-L. -l_b"
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=a.cpp DYLIB_NAME=_a \
LD_EXTRAS="-L. -l_b"

lib_b:
$(MAKE) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=_b
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=_b

lib_c:
$(MAKE) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=c.cpp DYLIB_NAME=_c
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=c.cpp DYLIB_NAME=_c

lib_d:
$(MAKE) -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=_d
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=_d
2 changes: 1 addition & 1 deletion lldb/test/API/lang/c/conflicting-symbol/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ include Makefile.rules
a.out: lib_One lib_Two

lib_%:
$(MAKE) VPATH=$(SRCDIR)/$* -I $(SRCDIR) -f $(SRCDIR)/$*.mk
"$(MAKE)" VPATH=$(SRCDIR)/$* -I $(SRCDIR) -f $(SRCDIR)/$*.mk
2 changes: 1 addition & 1 deletion lldb/test/API/lang/cpp/incomplete-types/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ main.o: CFLAGS_EXTRAS = -flimit-debug-info

limit: a.o main.o
mkdir -p build_limit
$(MAKE) -C $(BUILDDIR)/build_limit -f $(MAKEFILE_RULES) \
"$(MAKE)" -C $(BUILDDIR)/build_limit -f $(MAKEFILE_RULES) \
EXE=../limit CXX_SOURCES="length.cpp ../a.o ../main.o" \
CFLAGS_EXTRAS=-flimit-debug-info NO_LIMIT_DEBUG_INFO_FLAGS=""

4 changes: 2 additions & 2 deletions lldb/test/API/lang/cpp/namespace_definitions/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ a.out: liba libb
include Makefile.rules

liba:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=a DYLIB_CXX_SOURCES=a.cpp

libb:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=b DYLIB_CXX_SOURCES=b.cpp

4 changes: 2 additions & 2 deletions lldb/test/API/lang/objc/conflicting-definition/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ include Makefile.rules

libTest.dylib: Test/Test.m
mkdir -p Test
$(MAKE) MAKE_DSYM=YES -f $(MAKEFILE_RULES) \
"$(MAKE)" MAKE_DSYM=YES -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=Test DYLIB_OBJC_SOURCES=Test/Test.m \
LD_EXTRAS="-lobjc -framework Foundation" \
CFLAGS_EXTRAS=-I$(SRCDIR)

libTestExt.dylib: TestExt/TestExt.m
mkdir -p TestExt
$(MAKE) MAKE_DSYM=YES -f $(MAKEFILE_RULES) \
"$(MAKE)" MAKE_DSYM=YES -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=TestExt DYLIB_OBJC_SOURCES=TestExt/TestExt.m \
LD_EXTRAS="-lobjc -framework Foundation -lTest -L." \
CFLAGS_EXTRAS=-I$(SRCDIR)
Expand Down
2 changes: 1 addition & 1 deletion lldb/test/API/lang/objc/modules-hash-mismatch/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ USE_PRIVATE_MODULE_CACHE = YES
.PHONY: update-module

all: $(EXE)
$(MAKE) -f $(SRCDIR)/Makefile update-module
"$(MAKE)" -f $(SRCDIR)/Makefile update-module

include Makefile.rules

Expand Down
2 changes: 1 addition & 1 deletion lldb/test/API/macosx/delay-init-dependency/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ all: build-libfoo a.out
include Makefile.rules

build-libfoo: foo.c
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_C_SOURCES=foo.c DYLIB_NAME=foo DYLIB_ONLY=YES
2 changes: 1 addition & 1 deletion lldb/test/API/macosx/expedited-thread-pcs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ all: build-libfoo a.out
include Makefile.rules

build-libfoo: foo.c
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_C_SOURCES=foo.c DYLIB_NAME=foo DYLIB_ONLY=YES

4 changes: 2 additions & 2 deletions lldb/test/API/macosx/indirect_symbol/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ all: build-libindirect build-libreepxoprt a.out
include Makefile.rules

build-libindirect: indirect.c
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_C_SOURCES=indirect.c DYLIB_NAME=indirect DYLIB_ONLY=YES \
LD_EXTRAS="-Wl,-image_base,0x200000000"

build-libreepxoprt: reexport.c
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_C_SOURCES=reexport.c DYLIB_NAME=reexport DYLIB_ONLY=YES \
LD_EXTRAS="-L. -lindirect -Wl,-alias_list,$(SRCDIR)/alias.list"
2 changes: 1 addition & 1 deletion lldb/test/API/macosx/lc-note/kern-ver-str/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ C_SOURCES := main.c
all: a.out create-empty-corefile

create-empty-corefile:
$(MAKE) -f $(MAKEFILE_RULES) EXE=create-empty-corefile \
"$(MAKE)" -f $(MAKEFILE_RULES) EXE=create-empty-corefile \
CXX=$(CC) CXX_SOURCES=create-empty-corefile.cpp

include Makefile.rules
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ create-empty-corefile:
CXX_SOURCES=create-multibin-corefile.cpp

libone.dylib: one.c
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=one DYLIB_C_SOURCES=one.c

libtwo.dylib: two.c
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=two DYLIB_C_SOURCES=two.c

include Makefile.rules
2 changes: 1 addition & 1 deletion lldb/test/API/macosx/macCatalystAppMacOSFramework/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ override CC=xcrun clang
all: libfoo.dylib a.out

libfoo.dylib: foo.c
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_NAME=foo DYLIB_C_SOURCES=foo.c

include Makefile.rules
4 changes: 2 additions & 2 deletions lldb/test/API/macosx/skinny-corefile/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ include Makefile.rules
a.out: libto-be-removed libpresent

libto-be-removed: libpresent
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_C_SOURCES=to-be-removed.c DYLIB_NAME=to-be-removed \
LD_EXTRAS="-L. -lpresent"

libpresent:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_C_SOURCES=present.c DYLIB_NAME=present
2 changes: 1 addition & 1 deletion lldb/test/API/tools/lldb-dap/breakpoint/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ main-copy.cpp: main.cpp

# The following shared library will be used to test breakpoints under dynamic loading
libother: other-copy.c
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_ONLY=YES DYLIB_C_SOURCES=other-copy.c DYLIB_NAME=other
4 changes: 2 additions & 2 deletions lldb/test/API/tools/lldb-server/libraries-svr4/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ a.out: svr4lib_a svr4lib_b_quote
include Makefile.rules

svr4lib_a:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_NAME=svr4lib_a DYLIB_CXX_SOURCES=svr4lib_a.cpp \
DYLIB_ONLY=YES

svr4lib_b_quote:
$(MAKE) -f $(MAKEFILE_RULES) \
"$(MAKE)" -f $(MAKEFILE_RULES) \
DYLIB_NAME=svr4lib_b\\\" DYLIB_CXX_SOURCES=svr4lib_b_quote.cpp \
DYLIB_ONLY=YES
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// XFAIL: *

// RUN: %clangxx_host -gdwarf -o %t %s
// RUN: %clang --target=x86_64-apple-macosx -c -gdwarf -o %t %s
// RUN: %lldb %t \
// RUN: -o "expr alignof(OverlappingFields)" \
// RUN: -o "expr sizeof(OverlappingFields)" \
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// XFAIL: *

// RUN: %clangxx_host -gdwarf -o %t %s
// RUN: %clang --target=x86_64-apple-macosx -c -gdwarf -o %t %s
// RUN: %lldb %t \
// RUN: -o "expr alignof(OverlappingDerived)" \
// RUN: -o "expr sizeof(OverlappingDerived)" \
Expand Down
55 changes: 53 additions & 2 deletions lldb/unittests/Utility/DiagnosticsRenderingTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,63 @@ std::string Render(std::vector<DiagnosticDetail> details) {
} // namespace

TEST_F(ErrorDisplayTest, RenderStatus) {
DiagnosticDetail::SourceLocation inline_loc;
inline_loc.in_user_input = true;
using SourceLocation = DiagnosticDetail::SourceLocation;
{
SourceLocation inline_loc;
inline_loc.in_user_input = true;
std::string result =
Render({DiagnosticDetail{inline_loc, eSeverityError, "foo", ""}});
ASSERT_TRUE(StringRef(result).contains("error:"));
ASSERT_TRUE(StringRef(result).contains("foo"));
}

{
// Test that diagnostics on the same column can be handled and all
// three errors are diagnosed.
SourceLocation loc1 = {FileSpec{"a.c"}, 13, 11, 0, false, true};
SourceLocation loc2 = {FileSpec{"a.c"}, 13, 13, 0, false, true};
std::string result =
Render({DiagnosticDetail{loc1, eSeverityError, "1", "1"},
DiagnosticDetail{loc1, eSeverityError, "2", "2"},
DiagnosticDetail{loc2, eSeverityError, "3", "3"}});
ASSERT_TRUE(StringRef(result).contains("error: 1"));
ASSERT_TRUE(StringRef(result).contains("error: 2"));
ASSERT_TRUE(StringRef(result).contains("error: 3"));
}
{
// Test that diagnostics in reverse order are emitted correctly.
SourceLocation loc1 = {FileSpec{"a.c"}, 1, 20, 0, false, true};
SourceLocation loc2 = {FileSpec{"a.c"}, 2, 10, 0, false, true};
std::string result =
Render({DiagnosticDetail{loc2, eSeverityError, "X", "X"},
DiagnosticDetail{loc1, eSeverityError, "Y", "Y"}});
ASSERT_LT(StringRef(result).find("Y"), StringRef(result).find("X"));
}
{
// Test that diagnostics in reverse order are emitted correctly.
SourceLocation loc1 = {FileSpec{"a.c"}, 2, 10, 0, false, true};
SourceLocation loc2 = {FileSpec{"a.c"}, 1, 20, 0, false, true};
std::string result =
Render({DiagnosticDetail{loc2, eSeverityError, "X", "X"},
DiagnosticDetail{loc1, eSeverityError, "Y", "Y"}});
ASSERT_LT(StringRef(result).find("Y"), StringRef(result).find("X"));
}
{
// Test that range diagnostics are emitted correctly.
SourceLocation loc1 = {FileSpec{"a.c"}, 1, 1, 3, false, true};
SourceLocation loc2 = {FileSpec{"a.c"}, 1, 5, 3, false, true};
std::string result =
Render({DiagnosticDetail{loc1, eSeverityError, "X", "X"},
DiagnosticDetail{loc2, eSeverityError, "Y", "Y"}});
auto lines = StringRef(result).split('\n');
auto line1 = lines.first;
lines = lines.second.split('\n');
auto line2 = lines.first;
lines = lines.second.split('\n');
auto line3 = lines.first;
// 1234567
ASSERT_EQ(line1, "^~~ ^~~");
ASSERT_EQ(line2, "| error: Y");
ASSERT_EQ(line3, "error: X");
}
}
24 changes: 24 additions & 0 deletions llvm/include/llvm/CodeGen/EarlyIfConversion.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===- llvm/CodeGen/EarlyIfConversion.h -------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CODEGEN_EARLYIFCONVERSION_H
#define LLVM_CODEGEN_EARLYIFCONVERSION_H

#include "llvm/CodeGen/MachinePassManager.h"

namespace llvm {

class EarlyIfConverterPass : public PassInfoMixin<EarlyIfConverterPass> {
public:
PreservedAnalyses run(MachineFunction &MF,
MachineFunctionAnalysisManager &MFAM);
};

} // namespace llvm

#endif // LLVM_CODEGEN_EARLYIFCONVERSION_H
31 changes: 29 additions & 2 deletions llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -599,11 +599,22 @@ class LegalizeRuleSet {
LegalizeRuleSet &legalFor(std::initializer_list<LLT> Types) {
return actionFor(LegalizeAction::Legal, Types);
}
LegalizeRuleSet &legalFor(bool Pred, std::initializer_list<LLT> Types) {
if (!Pred)
return *this;
return actionFor(LegalizeAction::Legal, Types);
}
/// The instruction is legal when type indexes 0 and 1 is any type pair in the
/// given list.
LegalizeRuleSet &legalFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
return actionFor(LegalizeAction::Legal, Types);
}
LegalizeRuleSet &legalFor(bool Pred,
std::initializer_list<std::pair<LLT, LLT>> Types) {
if (!Pred)
return *this;
return actionFor(LegalizeAction::Legal, Types);
}
/// The instruction is legal when type index 0 is any type in the given list
/// and imm index 0 is anything.
LegalizeRuleSet &legalForTypeWithAnyImm(std::initializer_list<LLT> Types) {
Expand Down Expand Up @@ -846,12 +857,23 @@ class LegalizeRuleSet {
LegalizeRuleSet &customFor(std::initializer_list<LLT> Types) {
return actionFor(LegalizeAction::Custom, Types);
}
LegalizeRuleSet &customFor(bool Pred, std::initializer_list<LLT> Types) {
if (!Pred)
return *this;
return actionFor(LegalizeAction::Custom, Types);
}

/// The instruction is custom when type indexes 0 and 1 is any type pair in the
/// given list.
/// The instruction is custom when type indexes 0 and 1 is any type pair in
/// the given list.
LegalizeRuleSet &customFor(std::initializer_list<std::pair<LLT, LLT>> Types) {
return actionFor(LegalizeAction::Custom, Types);
}
LegalizeRuleSet &customFor(bool Pred,
std::initializer_list<std::pair<LLT, LLT>> Types) {
if (!Pred)
return *this;
return actionFor(LegalizeAction::Custom, Types);
}

LegalizeRuleSet &customForCartesianProduct(std::initializer_list<LLT> Types) {
return actionForCartesianProduct(LegalizeAction::Custom, Types);
Expand Down Expand Up @@ -990,6 +1012,11 @@ class LegalizeRuleSet {
scalarNarrowerThan(TypeIdx, Ty.getSizeInBits()),
changeTo(typeIdx(TypeIdx), Ty));
}
LegalizeRuleSet &minScalar(bool Pred, unsigned TypeIdx, const LLT Ty) {
if (!Pred)
return *this;
return minScalar(TypeIdx, Ty);
}

/// Ensure the scalar is at least as wide as Ty if condition is met.
LegalizeRuleSet &minScalarIf(LegalityPredicate Predicate, unsigned TypeIdx,
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/CodeGen/MIRParser/MIParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct VRegInfo {
} D;
Register VReg;
Register PreferredReg;
std::vector<uint8_t> Flags;
uint8_t Flags = 0;
};

using Name2RegClassMap = StringMap<const TargetRegisterClass *>;
Expand Down
65 changes: 55 additions & 10 deletions llvm/include/llvm/CodeGen/MachineTraceMetrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,13 @@
#ifndef LLVM_CODEGEN_MACHINETRACEMETRICS_H
#define LLVM_CODEGEN_MACHINETRACEMETRICS_H

#include "llvm/ADT/SparseSet.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SparseSet.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachinePassManager.h"
#include "llvm/CodeGen/TargetSchedule.h"

namespace llvm {
Expand Down Expand Up @@ -93,7 +94,7 @@ enum class MachineTraceStrategy {
TS_NumStrategies
};

class MachineTraceMetrics : public MachineFunctionPass {
class MachineTraceMetrics {
const MachineFunction *MF = nullptr;
const TargetInstrInfo *TII = nullptr;
const TargetRegisterInfo *TRI = nullptr;
Expand All @@ -102,19 +103,25 @@ class MachineTraceMetrics : public MachineFunctionPass {
TargetSchedModel SchedModel;

public:
friend class MachineTraceMetricsWrapperPass;
friend class Ensemble;
friend class Trace;

class Ensemble;

static char ID;
// For legacy pass.
MachineTraceMetrics() = default;

explicit MachineTraceMetrics(MachineFunction &MF, const MachineLoopInfo &LI) {
init(MF, LI);
}

MachineTraceMetrics();
MachineTraceMetrics(MachineTraceMetrics &&) = default;

void getAnalysisUsage(AnalysisUsage&) const override;
bool runOnMachineFunction(MachineFunction&) override;
void releaseMemory() override;
void verifyAnalysis() const override;
~MachineTraceMetrics();

void init(MachineFunction &Func, const MachineLoopInfo &LI);
void clear();

/// Per-basic block information that doesn't depend on the trace through the
/// block.
Expand Down Expand Up @@ -400,6 +407,12 @@ class MachineTraceMetrics : public MachineFunctionPass {
/// Call Ensemble::getTrace() again to update any trace handles.
void invalidate(const MachineBasicBlock *MBB);

/// Handle invalidation explicitly.
bool invalidate(MachineFunction &, const PreservedAnalyses &PA,
MachineFunctionAnalysisManager::Invalidator &);

void verifyAnalysis() const;

private:
// One entry per basic block, indexed by block number.
SmallVector<FixedBlockInfo, 4> BlockInfo;
Expand All @@ -412,8 +425,8 @@ class MachineTraceMetrics : public MachineFunctionPass {
SmallVector<unsigned, 0> ProcReleaseAtCycles;

// One ensemble per strategy.
Ensemble
*Ensembles[static_cast<size_t>(MachineTraceStrategy::TS_NumStrategies)];
std::unique_ptr<Ensemble>
Ensembles[static_cast<size_t>(MachineTraceStrategy::TS_NumStrategies)];

// Convert scaled resource usage to a cycle count that can be compared with
// latencies.
Expand All @@ -435,6 +448,38 @@ inline raw_ostream &operator<<(raw_ostream &OS,
return OS;
}

class MachineTraceMetricsAnalysis
: public AnalysisInfoMixin<MachineTraceMetricsAnalysis> {
friend AnalysisInfoMixin<MachineTraceMetricsAnalysis>;
static AnalysisKey Key;

public:
using Result = MachineTraceMetrics;
Result run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM);
};

/// Verifier pass for \c MachineTraceMetrics.
struct MachineTraceMetricsVerifierPass
: PassInfoMixin<MachineTraceMetricsVerifierPass> {
PreservedAnalyses run(MachineFunction &MF,
MachineFunctionAnalysisManager &MFAM);
static bool isRequired() { return true; }
};

class MachineTraceMetricsWrapperPass : public MachineFunctionPass {
public:
static char ID;
MachineTraceMetrics MTM;

MachineTraceMetricsWrapperPass();

void getAnalysisUsage(AnalysisUsage &) const override;
bool runOnMachineFunction(MachineFunction &) override;
void releaseMemory() override { MTM.clear(); }
void verifyAnalysis() const override { MTM.verifyAnalysis(); }
MachineTraceMetrics &getMTM() { return MTM; }
};

} // end namespace llvm

#endif // LLVM_CODEGEN_MACHINETRACEMETRICS_H
2 changes: 1 addition & 1 deletion llvm/include/llvm/CodeGen/Passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ namespace llvm {

/// EarlyIfConverter - This pass performs if-conversion on SSA form by
/// inserting cmov instructions.
extern char &EarlyIfConverterID;
extern char &EarlyIfConverterLegacyID;

/// EarlyIfPredicator - This pass performs if-conversion on SSA form by
/// predicating if/else block and insert select at the join point.
Expand Down
23 changes: 23 additions & 0 deletions llvm/include/llvm/CodeGen/SDPatternMatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,16 @@ inline BinaryOpc_match<LHS, RHS> m_Srl(const LHS &L, const RHS &R) {
return BinaryOpc_match<LHS, RHS>(ISD::SRL, L, R);
}

template <typename LHS, typename RHS>
inline BinaryOpc_match<LHS, RHS> m_Rotl(const LHS &L, const RHS &R) {
return BinaryOpc_match<LHS, RHS>(ISD::ROTL, L, R);
}

template <typename LHS, typename RHS>
inline BinaryOpc_match<LHS, RHS> m_Rotr(const LHS &L, const RHS &R) {
return BinaryOpc_match<LHS, RHS>(ISD::ROTR, L, R);
}

template <typename LHS, typename RHS>
inline BinaryOpc_match<LHS, RHS, true> m_FAdd(const LHS &L, const RHS &R) {
return BinaryOpc_match<LHS, RHS, true>(ISD::FADD, L, R);
Expand Down Expand Up @@ -822,6 +832,11 @@ inline UnaryOpc_match<Opnd, true> m_ChainedUnaryOp(unsigned Opc,
return UnaryOpc_match<Opnd, true>(Opc, Op);
}

template <typename Opnd>
inline UnaryOpc_match<Opnd> m_BSwap(const Opnd &Op) {
return UnaryOpc_match<Opnd>(ISD::BSWAP, Op);
}

template <typename Opnd>
inline UnaryOpc_match<Opnd> m_BitReverse(const Opnd &Op) {
return UnaryOpc_match<Opnd>(ISD::BITREVERSE, Op);
Expand Down Expand Up @@ -892,10 +907,18 @@ template <typename Opnd> inline UnaryOpc_match<Opnd> m_FPToSI(const Opnd &Op) {
return UnaryOpc_match<Opnd>(ISD::FP_TO_SINT, Op);
}

template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctpop(const Opnd &Op) {
return UnaryOpc_match<Opnd>(ISD::CTPOP, Op);
}

template <typename Opnd> inline UnaryOpc_match<Opnd> m_Ctlz(const Opnd &Op) {
return UnaryOpc_match<Opnd>(ISD::CTLZ, Op);
}

template <typename Opnd> inline UnaryOpc_match<Opnd> m_Cttz(const Opnd &Op) {
return UnaryOpc_match<Opnd>(ISD::CTTZ, Op);
}

// === Constants ===
struct ConstantInt_match {
APInt *BindVal;
Expand Down
Loading