137 changes: 64 additions & 73 deletions flang/test/HLFIR/maxloc-lowering.fir

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions flang/test/HLFIR/maxval-lowering.fir
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func.func @_QPmaxval2(%arg0: !fir.box<!fir.array<?x?xi32>> {fir.bindc_name = "a"
// CHECK: %[[ARG0:.*]]: !fir.box<!fir.array<?x?xi32>>
// CHECK: %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>>
// CHECK: %[[ARG2:.*]]: !fir.ref<index>
// CHECK-DAG: %[[TRUE:.*]] = arith.constant true
// CHECK-DAG: %[[ARRAY:.*]]:2 = hlfir.declare %[[ARG0]]
// CHECK-DAG: %[[RES:.*]]:2 = hlfir.declare %[[ARG1]]
// CHECK-DAG: %[[DIM_VAR:.*]]:2 = hlfir.declare %[[ARG2]]
Expand All @@ -63,7 +64,6 @@ func.func @_QPmaxval2(%arg0: !fir.box<!fir.array<?x?xi32>> {fir.bindc_name = "a"
// CHECK-NEXT: %[[SHIFT:.*]] = fir.shape_shift %[[BOX_DIMS]]#0, %[[BOX_DIMS]]#1
// TODO: fix alias analysis in hlfir.assign bufferization
// CHECK-NEXT: %[[TMP:.*]]:2 = hlfir.declare %[[ADDR]](%[[SHIFT]]) {uniq_name = ".tmp.intrinsic_result"}
// CHECK: %[[TRUE:.*]] = arith.constant true
// CHECK: %[[ASEXPR:.*]] = hlfir.as_expr %[[TMP]]#0 move %[[TRUE]] : (!fir.box<!fir.array<?xi32>>, i1) -> !hlfir.expr<?xi32>
// CHECK: hlfir.assign %[[ASEXPR]] to %[[RES]]#0
// CHECK: hlfir.destroy %[[ASEXPR]]
Expand Down Expand Up @@ -190,6 +190,7 @@ func.func @_QPmaxval6(%arg0: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_n
// CHECK-LABEL: func.func @_QPmaxval6(
// CHECK: %[[ARG0:.*]]: !fir.box<!fir.array<?x!fir.char<1,?>>>
// CHECK: %[[ARG1:.*]]: !fir.boxchar<1>
// CHECK-DAG: %[[TRUE:.*]] = arith.constant true
// CHECK-DAG: %[[ARRAY:.*]]:2 = hlfir.declare %[[ARG0]]
// CHECK-DAG: %[[UNBOXED:.*]]:2 = fir.unboxchar %[[ARG1]]
// CHECK-DAG: %[[RES:.*]]:2 = hlfir.declare %[[UNBOXED]]#0 typeparams %[[UNBOXED]]#1
Expand All @@ -210,7 +211,6 @@ func.func @_QPmaxval6(%arg0: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_n
// CHECK: %[[BOX_ELESIZE:.*]] = fir.box_elesize %[[RET]]
// CHECK-NEXT: %[[ADDR:.*]] = fir.box_addr %[[RET]]
// CHECK-NEXT: %[[TMP:.*]]:2 = hlfir.declare %[[ADDR]] typeparams %[[BOX_ELESIZE]] {uniq_name = ".tmp.intrinsic_result"}
// CHECK: %[[TRUE:.*]] = arith.constant true
// CHECK: %[[ASEXPR:.*]] = hlfir.as_expr %[[TMP]]#0 move %[[TRUE]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
// CHECK: hlfir.assign %[[ASEXPR]] to %[[RES]]#0
// CHECK: hlfir.destroy %[[ASEXPR]]
Expand Down
137 changes: 64 additions & 73 deletions flang/test/HLFIR/minloc-lowering.fir

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions flang/test/HLFIR/minval-lowering.fir
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func.func @_QPminval2(%arg0: !fir.box<!fir.array<?x?xi32>> {fir.bindc_name = "a"
// CHECK: %[[ARG0:.*]]: !fir.box<!fir.array<?x?xi32>>
// CHECK: %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>>
// CHECK: %[[ARG2:.*]]: !fir.ref<index>
// CHECK-DAG: %[[TRUE:.*]] = arith.constant true
// CHECK-DAG: %[[ARRAY:.*]]:2 = hlfir.declare %[[ARG0]]
// CHECK-DAG: %[[RES:.*]]:2 = hlfir.declare %[[ARG1]]
// CHECK-DAG: %[[DIM_VAR:.*]]:2 = hlfir.declare %[[ARG2]]
Expand All @@ -63,7 +64,6 @@ func.func @_QPminval2(%arg0: !fir.box<!fir.array<?x?xi32>> {fir.bindc_name = "a"
// CHECK-NEXT: %[[SHIFT:.*]] = fir.shape_shift %[[BOX_DIMS]]#0, %[[BOX_DIMS]]#1
// TODO: fix alias analysis in hlfir.assign bufferization
// CHECK-NEXT: %[[TMP:.*]]:2 = hlfir.declare %[[ADDR]](%[[SHIFT]]) {uniq_name = ".tmp.intrinsic_result"}
// CHECK: %[[TRUE:.*]] = arith.constant true
// CHECK: %[[ASEXPR:.*]] = hlfir.as_expr %[[TMP]]#0 move %[[TRUE]] : (!fir.box<!fir.array<?xi32>>, i1) -> !hlfir.expr<?xi32>
// CHECK: hlfir.assign %[[ASEXPR]] to %[[RES]]#0
// CHECK: hlfir.destroy %[[ASEXPR]]
Expand Down Expand Up @@ -151,6 +151,7 @@ func.func @_QPminval5(%arg0: !fir.ref<!fir.array<2xi32>> {fir.bindc_name = "s"})
}
// CHECK-LABEL: func.func @_QPminval5(
// CHECK: %[[ARG0:.*]]: !fir.ref<!fir.array<2xi32>>
// CHECK-DAG: %[[TRUE:.*]] = arith.constant true
// CHECK-DAG: %[[RET_BOX:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
// CHECK-DAG: %[[RET_ADDR:.*]] = fir.zero_bits !fir.heap<!fir.array<?xi32>>
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
Expand All @@ -161,7 +162,6 @@ func.func @_QPminval5(%arg0: !fir.ref<!fir.array<2xi32>> {fir.bindc_name = "s"})
// CHECK-DAG: %[[RES_VAR:.*]] = hlfir.declare %[[ARG0]](%[[RES_SHAPE:.*]])

// CHECK-DAG: %[[MASK_ALLOC:.*]] = fir.alloca !fir.logical<4>
// CHECK-DAG: %[[TRUE:.*]] = arith.constant true
// CHECK-DAG: %[[MASK_VAL:.*]] = fir.convert %[[TRUE]] : (i1) -> !fir.logical<4>
// CHECK-DAG: fir.store %[[MASK_VAL]] to %[[MASK_ALLOC]] : !fir.ref<!fir.logical<4>>
// CHECK-DAG: %[[MASK_BOX:.*]] = fir.embox %[[MASK_ALLOC]]
Expand Down Expand Up @@ -190,6 +190,7 @@ func.func @_QPminval6(%arg0: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_n
// CHECK-LABEL: func.func @_QPminval6(
// CHECK: %[[ARG0:.*]]: !fir.box<!fir.array<?x!fir.char<1,?>>>
// CHECK: %[[ARG1:.*]]: !fir.boxchar<1>
// CHECK-DAG: %[[TRUE:.*]] = arith.constant true
// CHECK-DAG: %[[ARRAY:.*]]:2 = hlfir.declare %[[ARG0]]
// CHECK-DAG: %[[UNBOXED:.*]]:2 = fir.unboxchar %[[ARG1]]
// CHECK-DAG: %[[RES:.*]]:2 = hlfir.declare %[[UNBOXED]]#0 typeparams %[[UNBOXED]]#1
Expand All @@ -210,7 +211,6 @@ func.func @_QPminval6(%arg0: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_n
// CHECK: %[[BOX_ELESIZE:.*]] = fir.box_elesize %[[RET]]
// CHECK-NEXT: %[[ADDR:.*]] = fir.box_addr %[[RET]]
// CHECK-NEXT: %[[TMP:.*]]:2 = hlfir.declare %[[ADDR]] typeparams %[[BOX_ELESIZE]] {uniq_name = ".tmp.intrinsic_result"}
// CHECK: %[[TRUE:.*]] = arith.constant true
// CHECK: %[[ASEXPR:.*]] = hlfir.as_expr %[[TMP]]#0 move %[[TRUE]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
// CHECK: hlfir.assign %[[ASEXPR]] to %[[RES]]#0
// CHECK: hlfir.destroy %[[ASEXPR]]
Expand Down
27 changes: 11 additions & 16 deletions flang/test/HLFIR/mul_transpose.f90
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,22 @@ subroutine mul_transpose(a, b, res)
! CHECK-LOWERING: %[[TRANSPOSE_RES_LD:.*]] = fir.load %[[TRANSPOSE_RES_BOX:.*]]
! CHECK-LOWERING: %[[TRANSPOSE_RES_ADDR:.*]] = fir.box_addr %[[TRANSPOSE_RES_LD]]
! CHECK-LOWERING: %[[TRANSPOSE_RES_VAR:.*]]:2 = hlfir.declare %[[TRANSPOSE_RES_ADDR]]({{.*}}) {uniq_name = ".tmp.intrinsic_result"}
! CHECK-LOWERING: %[[TRUE:.*]] = arith.constant true
! CHECK-LOWERING: %[[TRANSPOSE_EXPR:.*]] = hlfir.as_expr %[[TRANSPOSE_RES_VAR]]#0 move %[[TRUE]] : (!fir.box<!fir.array<?x?xf32>>, i1) -> !hlfir.expr<?x?xf32>
! CHECK-LOWERING: %[[TRANSPOSE_EXPR:.*]] = hlfir.as_expr %[[TRANSPOSE_RES_VAR]]#0 move {{.*}} : (!fir.box<!fir.array<?x?xf32>>, i1) -> !hlfir.expr<?x?xf32>
! CHECK-LOWERING: %[[TRANSPOSE_ASSOC:.*]]:3 = hlfir.associate %[[TRANSPOSE_EXPR]]({{.*}}) {adapt.valuebyref}
! CHECK-LOWERING: (!hlfir.expr<?x?xf32>, !fir.shape<2>) -> (!fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.array<?x?xf32>>, i1)
! CHECK-LOWERING: (!hlfir.expr<?x?xf32>, !fir.shape<2>) -> (!fir.ref<!fir.array<1x2xf32>>, !fir.ref<!fir.array<1x2xf32>>, i1)

! CHECK-LOWERING: %[[LHS_BOX:.*]] = fir.embox %[[TRANSPOSE_ASSOC]]#1
! CHECK-LOWERING: %[[B_BOX:.*]] = fir.embox %[[B_DECL]]#1(%{{.*}})
! CHECK-LOWERING: %[[MUL_CONV_RES:.*]] = fir.convert %[[MUL_RES_BOX:.*]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>) -> !fir.ref<!fir.box<none>>
! CHECK-LOWERING: %[[LHS_CONV:.*]] = fir.convert %[[LHS_BOX]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.box<none>
! CHECK-LOWERING: %[[LHS_CONV:.*]] = fir.convert %[[LHS_BOX]] : (!fir.box<!fir.array<1x2xf32>>) -> !fir.box<none>
! CHECK-LOWERING: %[[B_BOX_CONV:.*]] = fir.convert %[[B_BOX]] : (!fir.box<!fir.array<2x2xf32>>) -> !fir.box<none>
! CHECK-LOWERING: fir.call @_FortranAMatmul(%[[MUL_CONV_RES]], %[[LHS_CONV]], %[[B_BOX_CONV]], %[[LOC_STR2:.*]], %[[LOC_N2:.*]])
! CHECK-LOWERING: %[[MUL_RES_LD:.*]] = fir.load %[[MUL_RES_BOX:.*]]
! CHECK-LOWERING: %[[MUL_RES_ADDR:.*]] = fir.box_addr %[[MUL_RES_LD]]
! CHECK-LOWERING: %[[MUL_RES_VAR:.*]]:2 = hlfir.declare %[[MUL_RES_ADDR]]({{.*}}) {uniq_name = ".tmp.intrinsic_result"}
! CHECK-LOWERING: %[[TRUE2:.*]] = arith.constant true
! CHECK-LOWERING: %[[MUL_EXPR:.*]] = hlfir.as_expr %[[MUL_RES_VAR]]#0 move %[[TRUE2]] : (!fir.box<!fir.array<?x?xf32>>, i1) -> !hlfir.expr<?x?xf32>
! CHECK-LOWERING: %[[MUL_EXPR:.*]] = hlfir.as_expr %[[MUL_RES_VAR]]#0 move {{.*}} : (!fir.box<!fir.array<?x?xf32>>, i1) -> !hlfir.expr<?x?xf32>

! CHECK-LOWERING: hlfir.end_associate %[[TRANSPOSE_ASSOC]]#1, %[[TRANSPOSE_ASSOC]]#2 : !fir.ref<!fir.array<?x?xf32>>, i1
! CHECK-LOWERING: hlfir.end_associate %[[TRANSPOSE_ASSOC]]#1, %[[TRANSPOSE_ASSOC]]#2 : !fir.ref<!fir.array<1x2xf32>>, i1
! CHECK-LOWERING-NEXT: hlfir.assign %[[MUL_EXPR]] to %[[RES_DECL]]#0 : !hlfir.expr<?x?xf32>, !fir.ref<!fir.array<1x2xf32>>
! CHECK-LOWERING-NEXT: hlfir.destroy %[[MUL_EXPR]]
! CHECK-LOWERING-NEXT: hlfir.destroy %[[TRANSPOSE_EXPR]]
Expand All @@ -66,8 +64,7 @@ subroutine mul_transpose(a, b, res)
! CHECK-LOWERING-OPT: %[[MUL_RES_LD:.*]] = fir.load %[[MUL_RES_BOX:.*]]
! CHECK-LOWERING-OPT: %[[MUL_RES_ADDR:.*]] = fir.box_addr %[[MUL_RES_LD]]
! CHECK-LOWERING-OPT: %[[MUL_RES_VAR:.*]]:2 = hlfir.declare %[[MUL_RES_ADDR]]({{.*}}) {uniq_name = ".tmp.intrinsic_result"}
! CHECK-LOWERING-OPT: %[[TRUE2:.*]] = arith.constant true
! CHECK-LOWERING-OPT: %[[MUL_EXPR:.*]] = hlfir.as_expr %[[MUL_RES_VAR]]#0 move %[[TRUE2]] : (!fir.box<!fir.array<?x?xf32>>, i1) -> !hlfir.expr<?x?xf32>
! CHECK-LOWERING-OPT: %[[MUL_EXPR:.*]] = hlfir.as_expr %[[MUL_RES_VAR]]#0 move {{.*}} : (!fir.box<!fir.array<?x?xf32>>, i1) -> !hlfir.expr<?x?xf32>
! CHECK-LOWERING-OPT: hlfir.assign %[[MUL_EXPR]] to %[[RES_DECL]]#0 : !hlfir.expr<?x?xf32>, !fir.ref<!fir.array<1x2xf32>>
! CHECK-LOWERING-OPT: hlfir.destroy %[[MUL_EXPR]]

Expand All @@ -76,25 +73,23 @@ subroutine mul_transpose(a, b, res)
! CHECK-BUFFERING: %[[TRANSPOSE_RES_LD:.*]] = fir.load %[[TRANSPOSE_RES_BOX:.*]]
! CHECK-BUFFERING: %[[TRANSPOSE_RES_ADDR:.*]] = fir.box_addr %[[TRANSPOSE_RES_LD]]
! CHECK-BUFFERING: %[[TRANSPOSE_RES_VAR:.*]]:2 = hlfir.declare %[[TRANSPOSE_RES_ADDR]]({{.*}}) {uniq_name = ".tmp.intrinsic_result"}
! CHECK-BUFFERING: %[[TRUE:.*]] = arith.constant true
! CHECK-BUFFERING: %[[TUPLE0:.*]] = fir.undefined tuple<!fir.box<!fir.array<?x?xf32>>, i1>
! CHECK-BUFFERING: %[[TUPLE1:.*]] = fir.insert_value %[[TUPLE0]], %[[TRUE]], [1 : index]
! CHECK-BUFFERING: %[[TUPLE1:.*]] = fir.insert_value %[[TUPLE0]], {{.*}}, [1 : index]
! CHECK-BUFFERING: %[[TUPLE2:.*]] = fir.insert_value %[[TUPLE1]], %[[TRANSPOSE_RES_VAR]]#0, [0 : index]

! CHECK-BUFFERING: %[[TRANSPOSE_RES_REF:.*]] = fir.convert %[[TRANSPOSE_RES_VAR]]#1 : (!fir.heap<!fir.array<?x?xf32>>) -> !fir.ref<!fir.array<?x?xf32>>
! CHECK-BUFFERING: %[[TRANSPOSE_RES_REF:.*]] = fir.convert %[[TRANSPOSE_RES_VAR]]#1 : (!fir.heap<!fir.array<?x?xf32>>) -> !fir.ref<!fir.array<1x2xf32>>
! CHECK-BUFFERING: %[[TRANSPOSE_RES_BOX:.*]] = fir.embox %[[TRANSPOSE_RES_REF]]({{.*}})
! CHECK-BUFFERING: %[[LHS_CONV:.*]] = fir.convert %[[TRANSPOSE_RES_BOX]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.box<none>
! CHECK-BUFFERING: %[[LHS_CONV:.*]] = fir.convert %[[TRANSPOSE_RES_BOX]] : (!fir.box<!fir.array<1x2xf32>>) -> !fir.box<none>
! [argument handling unchanged]
! CHECK-BUFFERING: fir.call @_FortranAMatmul(
! CHECK-BUFFERING: %[[MUL_RES_LD:.*]] = fir.load %[[MUL_RES_BOX:.*]]
! CHECK-BUFFERING: %[[MUL_RES_ADDR:.*]] = fir.box_addr %[[MUL_RES_LD]]
! CHECK-BUFFERING: %[[MUL_RES_VAR:.*]]:2 = hlfir.declare %[[MUL_RES_ADDR]]({{.*}}) {uniq_name = ".tmp.intrinsic_result"}
! CHECK-BUFFERING: %[[TRUE2:.*]] = arith.constant true
! CHECK-BUFFERING: %[[TUPLE3:.*]] = fir.undefined tuple<!fir.box<!fir.array<?x?xf32>>, i1>
! CHECK-BUFFERING: %[[TUPLE4:.*]] = fir.insert_value %[[TUPLE3]], %[[TRUE2]], [1 : index]
! CHECK-BUFFERING: %[[TUPLE4:.*]] = fir.insert_value %[[TUPLE3]], {{.*}}, [1 : index]
! CHECK-BUFFERING: %[[TUPLE5:.*]] = fir.insert_value %[[TUPLE4]], %[[MUL_RES_VAR]]#0, [0 : index]

! CHECK-BUFFERING: %[[TRANSPOSE_RES_HEAP:.*]] = fir.convert %[[TRANSPOSE_RES_REF]] : (!fir.ref<!fir.array<?x?xf32>>) -> !fir.heap<!fir.array<?x?xf32>>
! CHECK-BUFFERING: %[[TRANSPOSE_RES_HEAP:.*]] = fir.convert %[[TRANSPOSE_RES_REF]] : (!fir.ref<!fir.array<1x2xf32>>) -> !fir.heap<!fir.array<1x2xf32>>
! CHECK-BUFFERING-NEXT: fir.freemem %[[TRANSPOSE_RES_HEAP]]
! CHECK-BUFFERING-NEXT: hlfir.assign %[[MUL_RES_VAR]]#0 to %[[RES_DECL]]#0 : !fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.array<1x2xf32>>
! CHECK-BUFFERING-NEXT: %[[MUL_RES_HEAP:.*]] = fir.box_addr %[[MUL_RES_VAR]]#0 : (!fir.box<!fir.array<?x?xf32>>) -> !fir.heap<!fir.array<?x?xf32>>
Expand Down
4 changes: 2 additions & 2 deletions flang/test/HLFIR/product-lowering.fir
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func.func @_QPproduct2(%arg0: !fir.box<!fir.array<?x?xi32>> {fir.bindc_name = "a
// CHECK: %[[ARG0:.*]]: !fir.box<!fir.array<?x?xi32>>
// CHECK: %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>>
// CHECK: %[[ARG2:.*]]: !fir.ref<index>
// CHECK-DAG: %[[TRUE:.*]] = arith.constant true
// CHECK-DAG: %[[ARRAY:.*]]:2 = hlfir.declare %[[ARG0]]
// CHECK-DAG: %[[DIM_VAR:.*]]:2 = hlfir.declare %[[ARG2]]
// CHECK-DAG: %[[RES:.*]]:2 = hlfir.declare %[[ARG1]]
Expand All @@ -64,7 +65,6 @@ func.func @_QPproduct2(%arg0: !fir.box<!fir.array<?x?xi32>> {fir.bindc_name = "a
// CHECK-NEXT: %[[ADDR:.*]] = fir.box_addr %[[RET]]
// CHECK-NEXT: %[[SHIFT:.*]] = fir.shape_shift %[[BOX_DIMS]]#0, %[[BOX_DIMS]]#1
// CHECK-NEXT: %[[TMP:.*]]:2 = hlfir.declare %[[ADDR]](%[[SHIFT]]) {uniq_name = ".tmp.intrinsic_result"}
// CHECK: %[[TRUE:.*]] = arith.constant true
// CHECK: %[[EXPR:.*]] = hlfir.as_expr %[[TMP]]#0 move %[[TRUE]] : (!fir.box<!fir.array<?xi32>>, i1) -> !hlfir.expr<?xi32>
// CHECK: hlfir.assign %[[EXPR]] to %[[RES]]#0
// CHECK: hlfir.destroy %[[EXPR]]
Expand Down Expand Up @@ -141,6 +141,7 @@ func.func @_QPproduct5(%arg0: !fir.ref<!fir.array<2xi32>> {fir.bindc_name = "s"}

// CHECK-LABEL: func.func @_QPproduct5(
// CHECK: %[[ARG0:.*]]: !fir.ref<!fir.array<2xi32>>
// CHECK-DAG: %[[TRUE:.*]] = arith.constant true
// CHECK-DAG: %[[RET_BOX:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
// CHECK-DAG: %[[RET_ADDR:.*]] = fir.zero_bits !fir.heap<!fir.array<?xi32>>
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
Expand All @@ -151,7 +152,6 @@ func.func @_QPproduct5(%arg0: !fir.ref<!fir.array<2xi32>> {fir.bindc_name = "s"}
// CHECK-DAG: %[[RES_VAR:.*]] = hlfir.declare %[[ARG0]](%[[RES_SHAPE:.*]])

// CHECK-DAG: %[[MASK_ALLOC:.*]] = fir.alloca !fir.logical<4>
// CHECK-DAG: %[[TRUE:.*]] = arith.constant true
// CHECK-DAG: %[[MASK_VAL:.*]] = fir.convert %[[TRUE]] : (i1) -> !fir.logical<4>
// CHECK-DAG: fir.store %[[MASK_VAL]] to %[[MASK_ALLOC]] : !fir.ref<!fir.logical<4>>
// CHECK-DAG: %[[MASK_BOX:.*]] = fir.embox %[[MASK_ALLOC]]
Expand Down
4 changes: 2 additions & 2 deletions flang/test/HLFIR/sum-lowering.fir
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func.func @_QPsum2(%arg0: !fir.box<!fir.array<?x?xi32>> {fir.bindc_name = "a"},
// CHECK: %[[ARG0:.*]]: !fir.box<!fir.array<?x?xi32>>
// CHECK: %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>>
// CHECK: %[[ARG2:.*]]: !fir.ref<index>
// CHECK-DAG: %[[TRUE:.*]] = arith.constant true
// CHECK-DAG: %[[ARRAY:.*]]:2 = hlfir.declare %[[ARG0]]
// CHECK-DAG: %[[RES:.*]]:2 = hlfir.declare %[[ARG1]]
// CHECK-DAG: %[[DIM_VAR:.*]]:2 = hlfir.declare %[[ARG2]]
Expand All @@ -63,7 +64,6 @@ func.func @_QPsum2(%arg0: !fir.box<!fir.array<?x?xi32>> {fir.bindc_name = "a"},
// CHECK-NEXT: %[[SHIFT:.*]] = fir.shape_shift %[[BOX_DIMS]]#0, %[[BOX_DIMS]]#1
// TODO: fix alias analysis in hlfir.assign bufferization
// CHECK-NEXT: %[[TMP:.*]]:2 = hlfir.declare %[[ADDR]](%[[SHIFT]]) {uniq_name = ".tmp.intrinsic_result"}
// CHECK: %[[TRUE:.*]] = arith.constant true
// CHECK: %[[ASEXPR:.*]] = hlfir.as_expr %[[TMP]]#0 move %[[TRUE]] : (!fir.box<!fir.array<?xi32>>, i1) -> !hlfir.expr<?xi32>
// CHECK: hlfir.assign %[[ASEXPR]] to %[[RES]]#0
// CHECK: hlfir.destroy %[[ASEXPR]]
Expand Down Expand Up @@ -151,6 +151,7 @@ func.func @_QPsum5(%arg0: !fir.ref<!fir.array<2xi32>> {fir.bindc_name = "s"}) {
}
// CHECK-LABEL: func.func @_QPsum5(
// CHECK: %[[ARG0:.*]]: !fir.ref<!fir.array<2xi32>>
// CHECK-DAG: %[[TRUE:.*]] = arith.constant true
// CHECK-DAG: %[[RET_BOX:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
// CHECK-DAG: %[[RET_ADDR:.*]] = fir.zero_bits !fir.heap<!fir.array<?xi32>>
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
Expand All @@ -161,7 +162,6 @@ func.func @_QPsum5(%arg0: !fir.ref<!fir.array<2xi32>> {fir.bindc_name = "s"}) {
// CHECK-DAG: %[[RES_VAR:.*]] = hlfir.declare %[[ARG0]](%[[RES_SHAPE:.*]])

// CHECK-DAG: %[[MASK_ALLOC:.*]] = fir.alloca !fir.logical<4>
// CHECK-DAG: %[[TRUE:.*]] = arith.constant true
// CHECK-DAG: %[[MASK_VAL:.*]] = fir.convert %[[TRUE]] : (i1) -> !fir.logical<4>
// CHECK-DAG: fir.store %[[MASK_VAL]] to %[[MASK_ALLOC]] : !fir.ref<!fir.logical<4>>
// CHECK-DAG: %[[MASK_BOX:.*]] = fir.embox %[[MASK_ALLOC]]
Expand Down
2 changes: 1 addition & 1 deletion flang/test/HLFIR/transpose-lowering.fir
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func.func @_QPtranspose1(%arg0: !fir.ref<!fir.array<1x2xi32>> {fir.bindc_name =
// CHECK-LABEL: func.func @_QPtranspose1(
// CHECK: %[[ARG0:.*]]: !fir.ref<!fir.array<1x2xi32>> {fir.bindc_name = "m"}
// CHECK: %[[ARG1:.*]]: !fir.ref<!fir.array<2x1xi32>> {fir.bindc_name = "res"}
// CHECK-DAG: %[[TRUE:.*]] = arith.constant true
// CHECK-DAG: %[[M_VAR:.*]]:2 = hlfir.declare %[[ARG0]]
// CHECK-DAG: %[[RES_VAR:.*]]:2 = hlfir.declare %[[ARG1]]

Expand All @@ -40,7 +41,6 @@ func.func @_QPtranspose1(%arg0: !fir.ref<!fir.array<1x2xi32>> {fir.bindc_name =
// CHECK-NEXT: %[[SHIFT:.*]] = fir.shape_shift %[[BOX_DIMS]]#0, %[[BOX_DIMS]]#1
// TODO: fix alias analysis in hlfir.assign bufferization
// CHECK-NEXT: %[[TMP:.*]]:2 = hlfir.declare %[[ADDR]](%[[SHIFT]]) {uniq_name = ".tmp.intrinsic_result"}
// CHECK: %[[TRUE:.*]] = arith.constant true
// CHECK: %[[ASEXPR:.*]] = hlfir.as_expr %[[TMP]]#0 move %[[TRUE]] : (!fir.box<!fir.array<?x?xi32>>, i1) -> !hlfir.expr<?x?xi32>
// CHECK: hlfir.assign %[[ASEXPR]] to %[[RES_VAR]]#0
// CHECK: hlfir.destroy %[[ASEXPR]]
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/convert.f90
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ program test
! ALL: fir.has_value %[[VAL_0]] : !fir.char<1,[[OPT_STR_LEN]]>

! ALL: fir.global linkonce @_QQEnvironmentDefaults.list constant : tuple<i[[int_size:.*]], !fir.ref<!fir.array<1xtuple<!fir.ref<i8>, !fir.ref<i8>>>>> {
! ALL: %[[VAL_0:.*]] = fir.undefined tuple<i[[int_size]], !fir.ref<!fir.array<1xtuple<!fir.ref<i8>, !fir.ref<i8>>>>>
! ALL: %[[VAL_1:.*]] = arith.constant 1 : i[[int_size]]
! ALL: %[[VAL_0:.*]] = fir.undefined tuple<i[[int_size]], !fir.ref<!fir.array<1xtuple<!fir.ref<i8>, !fir.ref<i8>>>>>
! ALL: %[[VAL_2:.*]] = fir.insert_value %[[VAL_0]], %[[VAL_1]], [0 : index] : (tuple<i[[int_size]], !fir.ref<!fir.array<1xtuple<!fir.ref<i8>, !fir.ref<i8>>>>>, i[[int_size]]) -> tuple<i[[int_size]], !fir.ref<!fir.array<1xtuple<!fir.ref<i8>, !fir.ref<i8>>>>>
! ALL: %[[VAL_3:.*]] = fir.address_of(@_QQEnvironmentDefaults.items) : !fir.ref<!fir.array<1xtuple<!fir.ref<i8>, !fir.ref<i8>>>>
! ALL: %[[VAL_4:.*]] = fir.insert_value %[[VAL_2]], %[[VAL_3]], [1 : index] : (tuple<i[[int_size]], !fir.ref<!fir.array<1xtuple<!fir.ref<i8>, !fir.ref<i8>>>>>, !fir.ref<!fir.array<1xtuple<!fir.ref<i8>, !fir.ref<i8>>>>) -> tuple<i[[int_size]], !fir.ref<!fir.array<1xtuple<!fir.ref<i8>, !fir.ref<i8>>>>>
Expand Down
57 changes: 57 additions & 0 deletions flang/test/Parser/assume-aligned.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
! RUN: %flang_fc1 -fdebug-unparse-no-sema %s 2>&1 | FileCheck %s

SUBROUTINE aa(a, nn)
IMPLICIT NONE
INTEGER, INTENT(IN) :: nn
COMPLEX(8), INTENT(INOUT), DIMENSION(1:nn) :: a
INTEGER :: i
!DIR$ assume_aligned a:16
!CHECK: !DIR$ ASSUME_ALIGNED a:16
!DIR$ assume_aligned a (1):16
!CHECK: !DIR$ ASSUME_ALIGNED a(1):16
!DIR$ assume_aligned a(1):16
!CHECK: !DIR$ ASSUME_ALIGNED a(1):16
!DIR$ assume_aligned a(nn):16
!CHECK: !DIR$ ASSUME_ALIGNED a(nn):16
!DIR$ assume_aligned a(44):16
!CHECK: !DIR$ ASSUME_ALIGNED a(44):16
DO i=1,nn
a(i)=a(i)+1.5
END DO
END SUBROUTINE aa

SUBROUTINE bb(v, s, e)
IMPLICIT NONE
INTEGER, INTENT(IN) :: s(3), e(3)
INTEGER :: y,z
REAL(8), INTENT(IN) :: v(s(1):e(1),s(2):e(2),s(3):e(3))
!DIR$ assume_aligned v(s(1),y,z) :64
!CHECK: !DIR$ ASSUME_ALIGNED v(s(1),y,z):64
END SUBROUTINE bb

SUBROUTINE f(n)
IMPLICIT NONE
TYPE node
REAL(KIND=8), POINTER :: a(:,:)
END TYPE NODE

TYPE(NODE), POINTER :: nodes
INTEGER :: i
INTEGER, INTENT(IN) :: n

ALLOCATE(nodes)
ALLOCATE(nodes%a(1000,1000))

!DIR$ ASSUME_ALIGNED nodes%a(1,1) : 16
!CHECK: !DIR$ ASSUME_ALIGNED nodes%a(1,1):16
DO i=1,n
nodes%a(1,i) = nodes%a(1,i)+1
END DO
END SUBROUTINE f

SUBROUTINE g(a, b)
IMPLICIT NONE
INTEGER, INTENT(in) :: a(128), b(128)
!DIR$ ASSUME_ALIGNED a:32, b:64
!CHECK: !DIR$ ASSUME_ALIGNED a:32, b:64
END SUBROUTINE g
9 changes: 5 additions & 4 deletions libc/cmake/modules/LLVMLibCArchitectures.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,14 @@ if(LIBC_TARGET_OS STREQUAL "baremetal")
set(LIBC_TARGET_OS_IS_BAREMETAL TRUE)
elseif(LIBC_TARGET_OS STREQUAL "linux")
set(LIBC_TARGET_OS_IS_LINUX TRUE)
elseif(LIBC_TARGET_OS STREQUAL "poky" OR LIBC_TARGET_OS STREQUAL "suse")
# poky are ustom Linux-base systems created by yocto. Since these are Linux
elseif(LIBC_TARGET_OS STREQUAL "poky" OR LIBC_TARGET_OS STREQUAL "suse" OR
LIBC_TARGET_OS STREQUAL "redhat")
# poky are custom Linux-base systems created by yocto. Since these are Linux
# images, we change the LIBC_TARGET_OS to linux. This define is used to
# include the right directories during compilation.
#
# openSUSE uses different triple format which causes LIBC_TARGET_OS to be
# computed as "suse" instead of "linux".
# openSUSE and redhat use different triple format which causes LIBC_TARGET_OS
# to be computed as "suse" or "redhat" instead of "linux".
set(LIBC_TARGET_OS_IS_LINUX TRUE)
set(LIBC_TARGET_OS "linux")
elseif(LIBC_TARGET_OS STREQUAL "darwin")
Expand Down
1 change: 1 addition & 0 deletions libc/include/llvm-libc-macros/float-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-include-next"
#pragma clang diagnostic ignored "-Winclude-next-absolute-path"
#else // gcc
#pragma GCC system_header
#endif //__clang__
Expand Down
4 changes: 3 additions & 1 deletion libcxx/docs/FeatureTestMacroTable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,8 @@ Status
--------------------------------------------------- -----------------
``__cpp_lib_ranges_chunk_by`` ``202202L``
--------------------------------------------------- -----------------
``__cpp_lib_ranges_contains`` ``202207L``
--------------------------------------------------- -----------------
``__cpp_lib_ranges_iota`` *unimplemented*
--------------------------------------------------- -----------------
``__cpp_lib_ranges_join_with`` *unimplemented*
Expand All @@ -362,7 +364,7 @@ Status
--------------------------------------------------- -----------------
``__cpp_lib_ranges_slide`` *unimplemented*
--------------------------------------------------- -----------------
``__cpp_lib_ranges_starts_ends_with`` *unimplemented*
``__cpp_lib_ranges_starts_ends_with`` ``202106L``
--------------------------------------------------- -----------------
``__cpp_lib_ranges_to_container`` ``202202L``
--------------------------------------------------- -----------------
Expand Down
3 changes: 2 additions & 1 deletion libcxx/docs/ReleaseNotes/19.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ Implemented Papers
- P2637R3 - Member ``visit``
- P2652R2 - Disallow User Specialization of ``allocator_traits``
- P2819R2 - Add ``tuple`` protocol to ``complex``

- P2302R4 - ``std::ranges::contains``
- P1659R3 - ``std::ranges::starts_with`` and ``std::ranges::ends_with``

Improvements and New Features
-----------------------------
Expand Down
4 changes: 2 additions & 2 deletions libcxx/docs/Status/Cxx23Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"`P1328R1 <https://wg21.link/P1328R1>`__","LWG","Making std::type_info::operator== constexpr","June 2021","|Complete|","17.0"
"`P1425R4 <https://wg21.link/P1425R4>`__","LWG","Iterators pair constructors for stack and queue","June 2021","|Complete|","14.0","|ranges|"
"`P1518R2 <https://wg21.link/P1518R2>`__","LWG","Stop overconstraining allocators in container deduction guides","June 2021","|Complete|","13.0"
"`P1659R3 <https://wg21.link/P1659R3>`__","LWG","starts_with and ends_with","June 2021","","","|ranges|"
"`P1659R3 <https://wg21.link/P1659R3>`__","LWG","starts_with and ends_with","June 2021","|Complete|","19.0","|ranges|"
"`P1951R1 <https://wg21.link/P1951R1>`__","LWG","Default Arguments for pair Forwarding Constructor","June 2021","|Complete|","14.0"
"`P1989R2 <https://wg21.link/P1989R2>`__","LWG","Range constructor for std::string_view","June 2021","|Complete|","14.0","|ranges|"
"`P2136R3 <https://wg21.link/P2136R3>`__","LWG","invoke_r","June 2021","|Complete|","17.0"
Expand Down Expand Up @@ -64,7 +64,7 @@
"`P2278R4 <https://wg21.link/P2278R4>`__","LWG","``cbegin`` should always return a constant iterator","July 2022","","","|ranges|"
"`P2286R8 <https://wg21.link/P2286R8>`__","LWG","Formatting Ranges","July 2022","|Complete|","16.0","|format| |ranges|"
"`P2291R3 <https://wg21.link/P2291R3>`__","LWG","Add Constexpr Modifiers to Functions ``to_chars`` and ``from_chars`` for Integral Types in ``<charconv>`` Header","July 2022","|Complete|","16.0"
"`P2302R4 <https://wg21.link/P2302R4>`__","LWG","``std::ranges::contains``","July 2022","","","|ranges|"
"`P2302R4 <https://wg21.link/P2302R4>`__","LWG","``std::ranges::contains``","July 2022","|Complete|","19.0","|ranges|"
"`P2322R6 <https://wg21.link/P2322R6>`__","LWG","``ranges::fold``","July 2022","","","|ranges|"
"`P2374R4 <https://wg21.link/P2374R4>`__","LWG","``views::cartesian_product``","July 2022","","","|ranges|"
"`P2404R3 <https://wg21.link/P2404R3>`__","LWG","Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with``","July 2022","",""
Expand Down
4 changes: 3 additions & 1 deletion libcxx/include/version
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ __cpp_lib_ranges_as_const 202207L <ranges>
__cpp_lib_ranges_as_rvalue 202207L <ranges>
__cpp_lib_ranges_chunk 202202L <ranges>
__cpp_lib_ranges_chunk_by 202202L <ranges>
__cpp_lib_ranges_contains 202207L <algorithm>
__cpp_lib_ranges_iota 202202L <numeric>
__cpp_lib_ranges_join_with 202202L <ranges>
__cpp_lib_ranges_repeat 202207L <ranges>
Expand Down Expand Up @@ -463,11 +464,12 @@ __cpp_lib_within_lifetime 202306L <type_traits>
# define __cpp_lib_ranges_as_rvalue 202207L
// # define __cpp_lib_ranges_chunk 202202L
# define __cpp_lib_ranges_chunk_by 202202L
# define __cpp_lib_ranges_contains 202207L
// # define __cpp_lib_ranges_iota 202202L
// # define __cpp_lib_ranges_join_with 202202L
# define __cpp_lib_ranges_repeat 202207L
// # define __cpp_lib_ranges_slide 202202L
// # define __cpp_lib_ranges_starts_ends_with 202106L
# define __cpp_lib_ranges_starts_ends_with 202106L
# define __cpp_lib_ranges_to_container 202202L
// # define __cpp_lib_ranges_zip 202110L
// # define __cpp_lib_reference_from_temporary 202202L
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
__cpp_lib_freestanding_algorithm 202311L [C++26]
__cpp_lib_parallel_algorithm 201603L [C++17]
__cpp_lib_ranges 202207L [C++20]
__cpp_lib_ranges_contains 202207L [C++23]
__cpp_lib_ranges_starts_ends_with 202106L [C++23]
__cpp_lib_robust_nonmodifying_seq_ops 201304L [C++14]
__cpp_lib_sample 201603L [C++17]
Expand Down Expand Up @@ -52,6 +53,10 @@
# error "__cpp_lib_ranges should not be defined before c++20"
# endif

# ifdef __cpp_lib_ranges_contains
# error "__cpp_lib_ranges_contains should not be defined before c++23"
# endif

# ifdef __cpp_lib_ranges_starts_ends_with
# error "__cpp_lib_ranges_starts_ends_with should not be defined before c++23"
# endif
Expand Down Expand Up @@ -90,6 +95,10 @@
# error "__cpp_lib_ranges should not be defined before c++20"
# endif

# ifdef __cpp_lib_ranges_contains
# error "__cpp_lib_ranges_contains should not be defined before c++23"
# endif

# ifdef __cpp_lib_ranges_starts_ends_with
# error "__cpp_lib_ranges_starts_ends_with should not be defined before c++23"
# endif
Expand Down Expand Up @@ -143,6 +152,10 @@
# error "__cpp_lib_ranges should not be defined before c++20"
# endif

# ifdef __cpp_lib_ranges_contains
# error "__cpp_lib_ranges_contains should not be defined before c++23"
# endif

# ifdef __cpp_lib_ranges_starts_ends_with
# error "__cpp_lib_ranges_starts_ends_with should not be defined before c++23"
# endif
Expand Down Expand Up @@ -205,6 +218,10 @@
# error "__cpp_lib_ranges should have the value 202207L in c++20"
# endif

# ifdef __cpp_lib_ranges_contains
# error "__cpp_lib_ranges_contains should not be defined before c++23"
# endif

# ifdef __cpp_lib_ranges_starts_ends_with
# error "__cpp_lib_ranges_starts_ends_with should not be defined before c++23"
# endif
Expand Down Expand Up @@ -270,17 +287,18 @@
# error "__cpp_lib_ranges should have the value 202207L in c++23"
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_ranges_starts_ends_with
# error "__cpp_lib_ranges_starts_ends_with should be defined in c++23"
# endif
# if __cpp_lib_ranges_starts_ends_with != 202106L
# error "__cpp_lib_ranges_starts_ends_with should have the value 202106L in c++23"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_ranges_starts_ends_with
# error "__cpp_lib_ranges_starts_ends_with should not be defined because it is unimplemented in libc++!"
# endif
# ifndef __cpp_lib_ranges_contains
# error "__cpp_lib_ranges_contains should be defined in c++23"
# endif
# if __cpp_lib_ranges_contains != 202207L
# error "__cpp_lib_ranges_contains should have the value 202207L in c++23"
# endif

# ifndef __cpp_lib_ranges_starts_ends_with
# error "__cpp_lib_ranges_starts_ends_with should be defined in c++23"
# endif
# if __cpp_lib_ranges_starts_ends_with != 202106L
# error "__cpp_lib_ranges_starts_ends_with should have the value 202106L in c++23"
# endif

# ifndef __cpp_lib_robust_nonmodifying_seq_ops
Expand Down Expand Up @@ -353,17 +371,18 @@
# error "__cpp_lib_ranges should have the value 202207L in c++26"
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_ranges_starts_ends_with
# error "__cpp_lib_ranges_starts_ends_with should be defined in c++26"
# endif
# if __cpp_lib_ranges_starts_ends_with != 202106L
# error "__cpp_lib_ranges_starts_ends_with should have the value 202106L in c++26"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_ranges_starts_ends_with
# error "__cpp_lib_ranges_starts_ends_with should not be defined because it is unimplemented in libc++!"
# endif
# ifndef __cpp_lib_ranges_contains
# error "__cpp_lib_ranges_contains should be defined in c++26"
# endif
# if __cpp_lib_ranges_contains != 202207L
# error "__cpp_lib_ranges_contains should have the value 202207L in c++26"
# endif

# ifndef __cpp_lib_ranges_starts_ends_with
# error "__cpp_lib_ranges_starts_ends_with should be defined in c++26"
# endif
# if __cpp_lib_ranges_starts_ends_with != 202106L
# error "__cpp_lib_ranges_starts_ends_with should have the value 202106L in c++26"
# endif

# ifndef __cpp_lib_robust_nonmodifying_seq_ops
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@
__cpp_lib_ranges_as_rvalue 202207L [C++23]
__cpp_lib_ranges_chunk 202202L [C++23]
__cpp_lib_ranges_chunk_by 202202L [C++23]
__cpp_lib_ranges_contains 202207L [C++23]
__cpp_lib_ranges_iota 202202L [C++23]
__cpp_lib_ranges_join_with 202202L [C++23]
__cpp_lib_ranges_repeat 202207L [C++23]
Expand Down Expand Up @@ -772,6 +773,10 @@
# error "__cpp_lib_ranges_chunk_by should not be defined before c++23"
# endif

# ifdef __cpp_lib_ranges_contains
# error "__cpp_lib_ranges_contains should not be defined before c++23"
# endif

# ifdef __cpp_lib_ranges_iota
# error "__cpp_lib_ranges_iota should not be defined before c++23"
# endif
Expand Down Expand Up @@ -1604,6 +1609,10 @@
# error "__cpp_lib_ranges_chunk_by should not be defined before c++23"
# endif

# ifdef __cpp_lib_ranges_contains
# error "__cpp_lib_ranges_contains should not be defined before c++23"
# endif

# ifdef __cpp_lib_ranges_iota
# error "__cpp_lib_ranges_iota should not be defined before c++23"
# endif
Expand Down Expand Up @@ -2607,6 +2616,10 @@
# error "__cpp_lib_ranges_chunk_by should not be defined before c++23"
# endif

# ifdef __cpp_lib_ranges_contains
# error "__cpp_lib_ranges_contains should not be defined before c++23"
# endif

# ifdef __cpp_lib_ranges_iota
# error "__cpp_lib_ranges_iota should not be defined before c++23"
# endif
Expand Down Expand Up @@ -3889,6 +3902,10 @@
# error "__cpp_lib_ranges_chunk_by should not be defined before c++23"
# endif

# ifdef __cpp_lib_ranges_contains
# error "__cpp_lib_ranges_contains should not be defined before c++23"
# endif

# ifdef __cpp_lib_ranges_iota
# error "__cpp_lib_ranges_iota should not be defined before c++23"
# endif
Expand Down Expand Up @@ -5357,6 +5374,13 @@
# error "__cpp_lib_ranges_chunk_by should have the value 202202L in c++23"
# endif

# ifndef __cpp_lib_ranges_contains
# error "__cpp_lib_ranges_contains should be defined in c++23"
# endif
# if __cpp_lib_ranges_contains != 202207L
# error "__cpp_lib_ranges_contains should have the value 202207L in c++23"
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_ranges_iota
# error "__cpp_lib_ranges_iota should be defined in c++23"
Expand Down Expand Up @@ -5403,17 +5427,11 @@
# endif
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_ranges_starts_ends_with
# error "__cpp_lib_ranges_starts_ends_with should be defined in c++23"
# endif
# if __cpp_lib_ranges_starts_ends_with != 202106L
# error "__cpp_lib_ranges_starts_ends_with should have the value 202106L in c++23"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_ranges_starts_ends_with
# error "__cpp_lib_ranges_starts_ends_with should not be defined because it is unimplemented in libc++!"
# endif
# ifndef __cpp_lib_ranges_starts_ends_with
# error "__cpp_lib_ranges_starts_ends_with should be defined in c++23"
# endif
# if __cpp_lib_ranges_starts_ends_with != 202106L
# error "__cpp_lib_ranges_starts_ends_with should have the value 202106L in c++23"
# endif

# ifndef __cpp_lib_ranges_to_container
Expand Down Expand Up @@ -7074,6 +7092,13 @@
# error "__cpp_lib_ranges_chunk_by should have the value 202202L in c++26"
# endif

# ifndef __cpp_lib_ranges_contains
# error "__cpp_lib_ranges_contains should be defined in c++26"
# endif
# if __cpp_lib_ranges_contains != 202207L
# error "__cpp_lib_ranges_contains should have the value 202207L in c++26"
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_ranges_iota
# error "__cpp_lib_ranges_iota should be defined in c++26"
Expand Down Expand Up @@ -7120,17 +7145,11 @@
# endif
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_ranges_starts_ends_with
# error "__cpp_lib_ranges_starts_ends_with should be defined in c++26"
# endif
# if __cpp_lib_ranges_starts_ends_with != 202106L
# error "__cpp_lib_ranges_starts_ends_with should have the value 202106L in c++26"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_ranges_starts_ends_with
# error "__cpp_lib_ranges_starts_ends_with should not be defined because it is unimplemented in libc++!"
# endif
# ifndef __cpp_lib_ranges_starts_ends_with
# error "__cpp_lib_ranges_starts_ends_with should be defined in c++26"
# endif
# if __cpp_lib_ranges_starts_ends_with != 202106L
# error "__cpp_lib_ranges_starts_ends_with should have the value 202106L in c++26"
# endif

# ifndef __cpp_lib_ranges_to_container
Expand Down
6 changes: 5 additions & 1 deletion libcxx/utils/generate_feature_test_macro_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,11 @@ def add_version_header(tc):
"values": {"c++23": 202202},
"headers": ["ranges"],
},
{
"name": "__cpp_lib_ranges_contains",
"values": {"c++23": 202207},
"headers": ["algorithm"],
},
{
"name": "__cpp_lib_ranges_iota",
"values": {"c++23": 202202},
Expand Down Expand Up @@ -941,7 +946,6 @@ def add_version_header(tc):
"name": "__cpp_lib_ranges_starts_ends_with",
"values": {"c++23": 202106},
"headers": ["algorithm"],
"unimplemented": True,
},
{
"name": "__cpp_lib_ranges_to_container",
Expand Down
3 changes: 3 additions & 0 deletions lldb/include/lldb/Core/Progress.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ class Progress {
///
/// @param [in] title The title of this progress activity.
///
/// @param [in] details Specific information about what the progress report
/// is currently working on.
///
/// @param [in] total The total units of work to be done if specified, if
/// set to std::nullopt then an indeterminate progress indicator should be
/// displayed.
Expand Down
5 changes: 5 additions & 0 deletions lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ static constexpr OptionEnumValueElement g_sort_option_enumeration[] = {
"name",
"Sort output by symbol name.",
},
{
eSortOrderBySize,
"size",
"Sort output by symbol byte size.",
},
};

// Note that the negation in the argument name causes a slightly confusing
Expand Down
7 changes: 6 additions & 1 deletion lldb/include/lldb/lldb-private-enumerations.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,12 @@ enum ArgumentRepetitionType {
// optional
};

enum SortOrder { eSortOrderNone, eSortOrderByAddress, eSortOrderByName };
enum SortOrder {
eSortOrderNone,
eSortOrderByAddress,
eSortOrderByName,
eSortOrderBySize
};

// LazyBool is for boolean values that need to be calculated lazily. Values
// start off set to eLazyBoolCalculate, and then they can be calculated once
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@


class DAPTestCaseBase(TestBase):
# set timeout based on whether ASAN was enabled or not. Increase
# timeout by a factor of 10 if ASAN is enabled.
timeoutval = 10 * (10 if ('ASAN_OPTIONS' in os.environ) else 1)
NO_DEBUG_INFO_TESTCASE = True

def create_debug_adaptor(self, lldbDAPEnv=None):
Expand Down
256 changes: 249 additions & 7 deletions lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Sema.h"
#include "llvm/Support/raw_ostream.h"
Expand All @@ -26,6 +28,7 @@

#include <memory>
#include <optional>
#include <type_traits>

using namespace lldb_private;
using namespace clang;
Expand Down Expand Up @@ -517,6 +520,236 @@ bool ClangASTImporter::CompleteType(const CompilerType &compiler_type) {
return false;
}

/// Copy layout information from \ref source_map to the \ref destination_map.
///
/// In the process of copying over layout info, we may need to import
/// decls from the \ref source_map. This function will use the supplied
/// \ref importer to import the necessary decls into \ref dest_ctx.
///
/// \param[in,out] dest_ctx Destination ASTContext into which we import
/// decls from the \ref source_map.
/// \param[out] destination_map A map from decls in \ref dest_ctx to an
/// integral offest, which will be copies
/// of the decl/offest pairs in \ref source_map
/// if successful.
/// \param[in] source_map A map from decls to integral offests. These will
/// be copied into \ref destination_map.
/// \param[in,out] importer Used to import decls into \ref dest_ctx.
///
/// \returns On success, will return 'true' and the offsets in \ref
/// destination_map
/// are usable copies of \ref source_map.
template <class D, class O>
static bool ImportOffsetMap(clang::ASTContext *dest_ctx,
llvm::DenseMap<const D *, O> &destination_map,
llvm::DenseMap<const D *, O> &source_map,
ClangASTImporter &importer) {
// When importing fields into a new record, clang has a hard requirement that
// fields be imported in field offset order. Since they are stored in a
// DenseMap with a pointer as the key type, this means we cannot simply
// iterate over the map, as the order will be non-deterministic. Instead we
// have to sort by the offset and then insert in sorted order.
typedef llvm::DenseMap<const D *, O> MapType;
typedef typename MapType::value_type PairType;
std::vector<PairType> sorted_items;
sorted_items.reserve(source_map.size());
sorted_items.assign(source_map.begin(), source_map.end());
llvm::sort(sorted_items, llvm::less_second());

for (const auto &item : sorted_items) {
DeclFromUser<D> user_decl(const_cast<D *>(item.first));
DeclFromParser<D> parser_decl(user_decl.Import(dest_ctx, importer));
if (parser_decl.IsInvalid())
return false;
destination_map.insert(
std::pair<const D *, O>(parser_decl.decl, item.second));
}

return true;
}

/// Given a CXXRecordDecl, will calculate and populate \ref base_offsets
/// with the integral offsets of any of its (possibly virtual) base classes.
///
/// \param[in] record_layout ASTRecordLayout of \ref record.
/// \param[in] record The record that we're calculating the base layouts of.
/// \param[out] base_offsets Map of base-class decl to integral offset which
/// this function will fill in.
///
/// \returns On success, will return 'true' and the offsets in \ref base_offsets
/// are usable.
template <bool IsVirtual>
bool ExtractBaseOffsets(const ASTRecordLayout &record_layout,
DeclFromUser<const CXXRecordDecl> &record,
llvm::DenseMap<const clang::CXXRecordDecl *,
clang::CharUnits> &base_offsets) {
for (CXXRecordDecl::base_class_const_iterator
bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()),
be = (IsVirtual ? record->vbases_end() : record->bases_end());
bi != be; ++bi) {
if (!IsVirtual && bi->isVirtual())
continue;

const clang::Type *origin_base_type = bi->getType().getTypePtr();
const clang::RecordType *origin_base_record_type =
origin_base_type->getAs<RecordType>();

if (!origin_base_record_type)
return false;

DeclFromUser<RecordDecl> origin_base_record(
origin_base_record_type->getDecl());

if (origin_base_record.IsInvalid())
return false;

DeclFromUser<CXXRecordDecl> origin_base_cxx_record(
DynCast<CXXRecordDecl>(origin_base_record));

if (origin_base_cxx_record.IsInvalid())
return false;

CharUnits base_offset;

if (IsVirtual)
base_offset =
record_layout.getVBaseClassOffset(origin_base_cxx_record.decl);
else
base_offset =
record_layout.getBaseClassOffset(origin_base_cxx_record.decl);

base_offsets.insert(std::pair<const CXXRecordDecl *, CharUnits>(
origin_base_cxx_record.decl, base_offset));
}

return true;
}

bool ClangASTImporter::importRecordLayoutFromOrigin(
const RecordDecl *record, uint64_t &size, uint64_t &alignment,
llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
&base_offsets,
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
&vbase_offsets) {

Log *log = GetLog(LLDBLog::Expressions);

clang::ASTContext &dest_ctx = record->getASTContext();
LLDB_LOG(log,
"LayoutRecordType on (ASTContext*){0} '{1}' for (RecordDecl*)"
"{2} [name = '{3}']",
&dest_ctx,
TypeSystemClang::GetASTContext(&dest_ctx)->getDisplayName(), record,
record->getName());

DeclFromParser<const RecordDecl> parser_record(record);
DeclFromUser<const RecordDecl> origin_record(parser_record.GetOrigin(*this));

if (origin_record.IsInvalid())
return false;

std::remove_reference_t<decltype(field_offsets)> origin_field_offsets;
std::remove_reference_t<decltype(base_offsets)> origin_base_offsets;
std::remove_reference_t<decltype(vbase_offsets)> origin_virtual_base_offsets;

TypeSystemClang::GetCompleteDecl(
&origin_record->getASTContext(),
const_cast<RecordDecl *>(origin_record.decl));

clang::RecordDecl *definition = origin_record.decl->getDefinition();
if (!definition || !definition->isCompleteDefinition())
return false;

const ASTRecordLayout &record_layout(
origin_record->getASTContext().getASTRecordLayout(origin_record.decl));

int field_idx = 0, field_count = record_layout.getFieldCount();

for (RecordDecl::field_iterator fi = origin_record->field_begin(),
fe = origin_record->field_end();
fi != fe; ++fi) {
if (field_idx >= field_count)
return false; // Layout didn't go well. Bail out.

uint64_t field_offset = record_layout.getFieldOffset(field_idx);

origin_field_offsets.insert(
std::pair<const FieldDecl *, uint64_t>(*fi, field_offset));

field_idx++;
}

DeclFromUser<const CXXRecordDecl> origin_cxx_record(
DynCast<const CXXRecordDecl>(origin_record));

if (origin_cxx_record.IsValid()) {
if (!ExtractBaseOffsets<false>(record_layout, origin_cxx_record,
origin_base_offsets) ||
!ExtractBaseOffsets<true>(record_layout, origin_cxx_record,
origin_virtual_base_offsets))
return false;
}

if (!ImportOffsetMap(&dest_ctx, field_offsets, origin_field_offsets, *this) ||
!ImportOffsetMap(&dest_ctx, base_offsets, origin_base_offsets, *this) ||
!ImportOffsetMap(&dest_ctx, vbase_offsets, origin_virtual_base_offsets,
*this))
return false;

size = record_layout.getSize().getQuantity() * dest_ctx.getCharWidth();
alignment =
record_layout.getAlignment().getQuantity() * dest_ctx.getCharWidth();

if (log) {
LLDB_LOG(log, "LRT returned:");
LLDB_LOG(log, "LRT Original = (RecordDecl*){0}",
static_cast<const void *>(origin_record.decl));
LLDB_LOG(log, "LRT Size = {0}", size);
LLDB_LOG(log, "LRT Alignment = {0}", alignment);
LLDB_LOG(log, "LRT Fields:");
for (RecordDecl::field_iterator fi = record->field_begin(),
fe = record->field_end();
fi != fe; ++fi) {
LLDB_LOG(log,
"LRT (FieldDecl*){0}, Name = '{1}', Type = '{2}', Offset = "
"{3} bits",
*fi, fi->getName(), fi->getType().getAsString(),
field_offsets[*fi]);
}
DeclFromParser<const CXXRecordDecl> parser_cxx_record =
DynCast<const CXXRecordDecl>(parser_record);
if (parser_cxx_record.IsValid()) {
LLDB_LOG(log, "LRT Bases:");
for (CXXRecordDecl::base_class_const_iterator
bi = parser_cxx_record->bases_begin(),
be = parser_cxx_record->bases_end();
bi != be; ++bi) {
bool is_virtual = bi->isVirtual();

QualType base_type = bi->getType();
const RecordType *base_record_type = base_type->getAs<RecordType>();
DeclFromParser<RecordDecl> base_record(base_record_type->getDecl());
DeclFromParser<CXXRecordDecl> base_cxx_record =
DynCast<CXXRecordDecl>(base_record);

LLDB_LOG(log,
"LRT {0}(CXXRecordDecl*){1}, Name = '{2}', Offset = "
"{3} chars",
(is_virtual ? "Virtual " : ""), base_cxx_record.decl,
base_cxx_record.decl->getName(),
(is_virtual
? vbase_offsets[base_cxx_record.decl].getQuantity()
: base_offsets[base_cxx_record.decl].getQuantity()));
}
} else {
LLDB_LOG(log, "LRD Not a CXXRecord, so no bases");
}
}

return true;
}

bool ClangASTImporter::LayoutRecordType(
const clang::RecordDecl *record_decl, uint64_t &bit_size,
uint64_t &alignment,
Expand All @@ -527,7 +760,6 @@ bool ClangASTImporter::LayoutRecordType(
&vbase_offsets) {
RecordDeclToLayoutMap::iterator pos =
m_record_decl_to_layout_map.find(record_decl);
bool success = false;
base_offsets.clear();
vbase_offsets.clear();
if (pos != m_record_decl_to_layout_map.end()) {
Expand All @@ -537,13 +769,23 @@ bool ClangASTImporter::LayoutRecordType(
base_offsets.swap(pos->second.base_offsets);
vbase_offsets.swap(pos->second.vbase_offsets);
m_record_decl_to_layout_map.erase(pos);
success = true;
} else {
bit_size = 0;
alignment = 0;
field_offsets.clear();
return true;
}
return success;

// It's possible that we calculated the layout in a different
// ClangASTImporter instance. Try to import such layout if
// our decl has an origin.
if (auto origin = GetDeclOrigin(record_decl); origin.Valid())
if (importRecordLayoutFromOrigin(record_decl, bit_size, alignment,
field_offsets, base_offsets,
vbase_offsets))
return true;

bit_size = 0;
alignment = 0;
field_offsets.clear();

return false;
}

void ClangASTImporter::SetRecordLayout(clang::RecordDecl *decl,
Expand Down
74 changes: 74 additions & 0 deletions lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <set>
#include <vector>

#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTImporter.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Decl.h"
Expand Down Expand Up @@ -127,6 +128,27 @@ class ClangASTImporter {
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
&vbase_offsets);

/// If \ref record has a valid origin, this function copies that
/// origin's layout into this ClangASTImporter instance.
///
/// \param[in] record The decl whose layout we're calculating.
/// \param[out] size Size of \ref record in bytes.
/// \param[out] alignment Alignment of \ref record in bytes.
/// \param[out] field_offsets Offsets of fields of \ref record.
/// \param[out] base_offsets Offsets of base classes of \ref record.
/// \param[out] vbase_offsets Offsets of virtual base classes of \ref record.
///
/// \returns Returns 'false' if no valid origin was found for \ref record or
/// this function failed to import the layout from the origin. Otherwise,
/// returns 'true' and the offsets/size/alignment are valid for use.
bool importRecordLayoutFromOrigin(
const clang::RecordDecl *record, uint64_t &size, uint64_t &alignment,
llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
&base_offsets,
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
&vbase_offsets);

/// Returns true iff the given type was copied from another TypeSystemClang
/// and the original type in this other TypeSystemClang might contain
/// additional information (e.g., the definition of a 'class' type) that could
Expand Down Expand Up @@ -456,6 +478,58 @@ class ClangASTImporter {
RecordDeclToLayoutMap m_record_decl_to_layout_map;
};

template <class D> class TaggedASTDecl {
public:
TaggedASTDecl() : decl(nullptr) {}
TaggedASTDecl(D *_decl) : decl(_decl) {}
bool IsValid() const { return (decl != nullptr); }
bool IsInvalid() const { return !IsValid(); }
D *operator->() const { return decl; }
D *decl;
};

template <class D2, template <class D> class TD, class D1>
TD<D2> DynCast(TD<D1> source) {
return TD<D2>(llvm::dyn_cast<D2>(source.decl));
}

template <class D = clang::Decl> class DeclFromParser;
template <class D = clang::Decl> class DeclFromUser;

template <class D> class DeclFromParser : public TaggedASTDecl<D> {
public:
DeclFromParser() : TaggedASTDecl<D>() {}
DeclFromParser(D *_decl) : TaggedASTDecl<D>(_decl) {}

DeclFromUser<D> GetOrigin(ClangASTImporter &importer);
};

template <class D> class DeclFromUser : public TaggedASTDecl<D> {
public:
DeclFromUser() : TaggedASTDecl<D>() {}
DeclFromUser(D *_decl) : TaggedASTDecl<D>(_decl) {}

DeclFromParser<D> Import(clang::ASTContext *dest_ctx,
ClangASTImporter &importer);
};

template <class D>
DeclFromUser<D> DeclFromParser<D>::GetOrigin(ClangASTImporter &importer) {
ClangASTImporter::DeclOrigin origin = importer.GetDeclOrigin(this->decl);
if (!origin.Valid())
return DeclFromUser<D>();
return DeclFromUser<D>(llvm::dyn_cast<D>(origin.decl));
}

template <class D>
DeclFromParser<D> DeclFromUser<D>::Import(clang::ASTContext *dest_ctx,
ClangASTImporter &importer) {
DeclFromParser<> parser_generic_decl(importer.CopyDecl(dest_ctx, this->decl));
if (parser_generic_decl.IsInvalid())
return DeclFromParser<D>();
return DeclFromParser<D>(llvm::dyn_cast<D>(parser_generic_decl.decl));
}

} // namespace lldb_private

#endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTIMPORTER_H
278 changes: 19 additions & 259 deletions lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/SourceManager.h"

#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
Expand Down Expand Up @@ -705,56 +704,6 @@ void ClangASTSource::FillNamespaceMap(
}
}

template <class D> class TaggedASTDecl {
public:
TaggedASTDecl() : decl(nullptr) {}
TaggedASTDecl(D *_decl) : decl(_decl) {}
bool IsValid() const { return (decl != nullptr); }
bool IsInvalid() const { return !IsValid(); }
D *operator->() const { return decl; }
D *decl;
};

template <class D2, template <class D> class TD, class D1>
TD<D2> DynCast(TD<D1> source) {
return TD<D2>(dyn_cast<D2>(source.decl));
}

template <class D = Decl> class DeclFromParser;
template <class D = Decl> class DeclFromUser;

template <class D> class DeclFromParser : public TaggedASTDecl<D> {
public:
DeclFromParser() : TaggedASTDecl<D>() {}
DeclFromParser(D *_decl) : TaggedASTDecl<D>(_decl) {}

DeclFromUser<D> GetOrigin(ClangASTSource &source);
};

template <class D> class DeclFromUser : public TaggedASTDecl<D> {
public:
DeclFromUser() : TaggedASTDecl<D>() {}
DeclFromUser(D *_decl) : TaggedASTDecl<D>(_decl) {}

DeclFromParser<D> Import(ClangASTSource &source);
};

template <class D>
DeclFromUser<D> DeclFromParser<D>::GetOrigin(ClangASTSource &source) {
ClangASTImporter::DeclOrigin origin = source.GetDeclOrigin(this->decl);
if (!origin.Valid())
return DeclFromUser<D>();
return DeclFromUser<D>(dyn_cast<D>(origin.decl));
}

template <class D>
DeclFromParser<D> DeclFromUser<D>::Import(ClangASTSource &source) {
DeclFromParser<> parser_generic_decl(source.CopyDecl(this->decl));
if (parser_generic_decl.IsInvalid())
return DeclFromParser<D>();
return DeclFromParser<D>(dyn_cast<D>(parser_generic_decl.decl));
}

bool ClangASTSource::FindObjCMethodDeclsWithOrigin(
NameSearchContext &context, ObjCInterfaceDecl *original_interface_decl,
const char *log_info) {
Expand Down Expand Up @@ -1188,8 +1137,8 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) {
} while (false);
}

static bool FindObjCPropertyAndIvarDeclsWithOrigin(
NameSearchContext &context, ClangASTSource &source,
bool ClangASTSource::FindObjCPropertyAndIvarDeclsWithOrigin(
NameSearchContext &context,
DeclFromUser<const ObjCInterfaceDecl> &origin_iface_decl) {
Log *log = GetLog(LLDBLog::Expressions);

Expand All @@ -1209,7 +1158,7 @@ static bool FindObjCPropertyAndIvarDeclsWithOrigin(

if (origin_property_decl.IsValid()) {
DeclFromParser<ObjCPropertyDecl> parser_property_decl(
origin_property_decl.Import(source));
origin_property_decl.Import(m_ast_context, *m_ast_importer_sp));
if (parser_property_decl.IsValid()) {
LLDB_LOG(log, " CAS::FOPD found\n{0}",
ClangUtil::DumpDecl(parser_property_decl.decl));
Expand All @@ -1224,7 +1173,7 @@ static bool FindObjCPropertyAndIvarDeclsWithOrigin(

if (origin_ivar_decl.IsValid()) {
DeclFromParser<ObjCIvarDecl> parser_ivar_decl(
origin_ivar_decl.Import(source));
origin_ivar_decl.Import(m_ast_context, *m_ast_importer_sp));
if (parser_ivar_decl.IsValid()) {
LLDB_LOG(log, " CAS::FOPD found\n{0}",
ClangUtil::DumpDecl(parser_ivar_decl.decl));
Expand All @@ -1243,7 +1192,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) {
DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl(
cast<ObjCInterfaceDecl>(context.m_decl_context));
DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl(
parser_iface_decl.GetOrigin(*this));
parser_iface_decl.GetOrigin(*m_ast_importer_sp));

ConstString class_name(parser_iface_decl->getNameAsString().c_str());

Expand All @@ -1253,7 +1202,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) {
m_ast_context, m_clang_ast_context->getDisplayName(),
parser_iface_decl->getName(), context.m_decl_name.getAsString());

if (FindObjCPropertyAndIvarDeclsWithOrigin(context, *this, origin_iface_decl))
if (FindObjCPropertyAndIvarDeclsWithOrigin(context, origin_iface_decl))
return;

LLDB_LOG(log,
Expand Down Expand Up @@ -1286,7 +1235,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) {
"(ObjCInterfaceDecl*){0}/(ASTContext*){1}...",
complete_iface_decl.decl, &complete_iface_decl->getASTContext());

FindObjCPropertyAndIvarDeclsWithOrigin(context, *this, complete_iface_decl);
FindObjCPropertyAndIvarDeclsWithOrigin(context, complete_iface_decl);

return;
} while (false);
Expand Down Expand Up @@ -1320,7 +1269,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) {
interface_decl_from_modules.decl,
&interface_decl_from_modules->getASTContext());

if (FindObjCPropertyAndIvarDeclsWithOrigin(context, *this,
if (FindObjCPropertyAndIvarDeclsWithOrigin(context,
interface_decl_from_modules))
return;
} while (false);
Expand Down Expand Up @@ -1364,7 +1313,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) {
interface_decl_from_runtime.decl,
&interface_decl_from_runtime->getASTContext());

if (FindObjCPropertyAndIvarDeclsWithOrigin(context, *this,
if (FindObjCPropertyAndIvarDeclsWithOrigin(context,
interface_decl_from_runtime))
return;
} while (false);
Expand Down Expand Up @@ -1395,205 +1344,16 @@ void ClangASTSource::LookupInNamespace(NameSearchContext &context) {
}
}

typedef llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsetMap;
typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetMap;

template <class D, class O>
static bool ImportOffsetMap(llvm::DenseMap<const D *, O> &destination_map,
llvm::DenseMap<const D *, O> &source_map,
ClangASTSource &source) {
// When importing fields into a new record, clang has a hard requirement that
// fields be imported in field offset order. Since they are stored in a
// DenseMap with a pointer as the key type, this means we cannot simply
// iterate over the map, as the order will be non-deterministic. Instead we
// have to sort by the offset and then insert in sorted order.
typedef llvm::DenseMap<const D *, O> MapType;
typedef typename MapType::value_type PairType;
std::vector<PairType> sorted_items;
sorted_items.reserve(source_map.size());
sorted_items.assign(source_map.begin(), source_map.end());
llvm::sort(sorted_items, llvm::less_second());

for (const auto &item : sorted_items) {
DeclFromUser<D> user_decl(const_cast<D *>(item.first));
DeclFromParser<D> parser_decl(user_decl.Import(source));
if (parser_decl.IsInvalid())
return false;
destination_map.insert(
std::pair<const D *, O>(parser_decl.decl, item.second));
}

return true;
}

template <bool IsVirtual>
bool ExtractBaseOffsets(const ASTRecordLayout &record_layout,
DeclFromUser<const CXXRecordDecl> &record,
BaseOffsetMap &base_offsets) {
for (CXXRecordDecl::base_class_const_iterator
bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()),
be = (IsVirtual ? record->vbases_end() : record->bases_end());
bi != be; ++bi) {
if (!IsVirtual && bi->isVirtual())
continue;

const clang::Type *origin_base_type = bi->getType().getTypePtr();
const clang::RecordType *origin_base_record_type =
origin_base_type->getAs<RecordType>();

if (!origin_base_record_type)
return false;

DeclFromUser<RecordDecl> origin_base_record(
origin_base_record_type->getDecl());

if (origin_base_record.IsInvalid())
return false;

DeclFromUser<CXXRecordDecl> origin_base_cxx_record(
DynCast<CXXRecordDecl>(origin_base_record));

if (origin_base_cxx_record.IsInvalid())
return false;

CharUnits base_offset;

if (IsVirtual)
base_offset =
record_layout.getVBaseClassOffset(origin_base_cxx_record.decl);
else
base_offset =
record_layout.getBaseClassOffset(origin_base_cxx_record.decl);

base_offsets.insert(std::pair<const CXXRecordDecl *, CharUnits>(
origin_base_cxx_record.decl, base_offset));
}

return true;
}

bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size,
uint64_t &alignment,
FieldOffsetMap &field_offsets,
BaseOffsetMap &base_offsets,
BaseOffsetMap &virtual_base_offsets) {

Log *log = GetLog(LLDBLog::Expressions);

LLDB_LOG(log,
"LayoutRecordType on (ASTContext*){0} '{1}' for (RecordDecl*)"
"{2} [name = '{3}']",
m_ast_context, m_clang_ast_context->getDisplayName(), record,
record->getName());

DeclFromParser<const RecordDecl> parser_record(record);
DeclFromUser<const RecordDecl> origin_record(
parser_record.GetOrigin(*this));

if (origin_record.IsInvalid())
return false;

FieldOffsetMap origin_field_offsets;
BaseOffsetMap origin_base_offsets;
BaseOffsetMap origin_virtual_base_offsets;

TypeSystemClang::GetCompleteDecl(
&origin_record->getASTContext(),
const_cast<RecordDecl *>(origin_record.decl));

clang::RecordDecl *definition = origin_record.decl->getDefinition();
if (!definition || !definition->isCompleteDefinition())
return false;

const ASTRecordLayout &record_layout(
origin_record->getASTContext().getASTRecordLayout(origin_record.decl));

int field_idx = 0, field_count = record_layout.getFieldCount();

for (RecordDecl::field_iterator fi = origin_record->field_begin(),
fe = origin_record->field_end();
fi != fe; ++fi) {
if (field_idx >= field_count)
return false; // Layout didn't go well. Bail out.

uint64_t field_offset = record_layout.getFieldOffset(field_idx);

origin_field_offsets.insert(
std::pair<const FieldDecl *, uint64_t>(*fi, field_offset));

field_idx++;
}

lldbassert(&record->getASTContext() == m_ast_context);

DeclFromUser<const CXXRecordDecl> origin_cxx_record(
DynCast<const CXXRecordDecl>(origin_record));

if (origin_cxx_record.IsValid()) {
if (!ExtractBaseOffsets<false>(record_layout, origin_cxx_record,
origin_base_offsets) ||
!ExtractBaseOffsets<true>(record_layout, origin_cxx_record,
origin_virtual_base_offsets))
return false;
}

if (!ImportOffsetMap(field_offsets, origin_field_offsets, *this) ||
!ImportOffsetMap(base_offsets, origin_base_offsets, *this) ||
!ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets,
*this))
return false;

size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth();
alignment = record_layout.getAlignment().getQuantity() *
m_ast_context->getCharWidth();

if (log) {
LLDB_LOG(log, "LRT returned:");
LLDB_LOG(log, "LRT Original = (RecordDecl*){0}",
static_cast<const void *>(origin_record.decl));
LLDB_LOG(log, "LRT Size = {0}", size);
LLDB_LOG(log, "LRT Alignment = {0}", alignment);
LLDB_LOG(log, "LRT Fields:");
for (RecordDecl::field_iterator fi = record->field_begin(),
fe = record->field_end();
fi != fe; ++fi) {
LLDB_LOG(log,
"LRT (FieldDecl*){0}, Name = '{1}', Type = '{2}', Offset = "
"{3} bits",
*fi, fi->getName(), fi->getType().getAsString(),
field_offsets[*fi]);
}
DeclFromParser<const CXXRecordDecl> parser_cxx_record =
DynCast<const CXXRecordDecl>(parser_record);
if (parser_cxx_record.IsValid()) {
LLDB_LOG(log, "LRT Bases:");
for (CXXRecordDecl::base_class_const_iterator
bi = parser_cxx_record->bases_begin(),
be = parser_cxx_record->bases_end();
bi != be; ++bi) {
bool is_virtual = bi->isVirtual();

QualType base_type = bi->getType();
const RecordType *base_record_type = base_type->getAs<RecordType>();
DeclFromParser<RecordDecl> base_record(base_record_type->getDecl());
DeclFromParser<CXXRecordDecl> base_cxx_record =
DynCast<CXXRecordDecl>(base_record);

LLDB_LOG(log,
"LRT {0}(CXXRecordDecl*){1}, Name = '{2}', Offset = "
"{3} chars",
(is_virtual ? "Virtual " : ""), base_cxx_record.decl,
base_cxx_record.decl->getName(),
(is_virtual
? virtual_base_offsets[base_cxx_record.decl].getQuantity()
: base_offsets[base_cxx_record.decl].getQuantity()));
}
} else {
LLDB_LOG(log, "LRD Not a CXXRecord, so no bases");
}
}

return true;
bool ClangASTSource::layoutRecordType(
const RecordDecl *record, uint64_t &size, uint64_t &alignment,
llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
&base_offsets,
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
&virtual_base_offsets) {
return m_ast_importer_sp->importRecordLayoutFromOrigin(
record, size, alignment, field_offsets, base_offsets,
virtual_base_offsets);
}

void ClangASTSource::CompleteNamespaceMap(
Expand Down
5 changes: 5 additions & 0 deletions lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,11 @@ class ClangASTSource : public clang::ExternalASTSource,
/// ExternalASTSource.
TypeSystemClang *GetTypeSystem() const { return m_clang_ast_context; }

private:
bool FindObjCPropertyAndIvarDeclsWithOrigin(
NameSearchContext &context,
DeclFromUser<const clang::ObjCInterfaceDecl> &origin_iface_decl);

protected:
bool FindObjCMethodDeclsWithOrigin(
NameSearchContext &context,
Expand Down
23 changes: 17 additions & 6 deletions lldb/source/Symbol/Symtab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,8 @@ void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order,
DumpSymbolHeader(s);

std::multimap<llvm::StringRef, const Symbol *> name_map;
for (const_iterator pos = m_symbols.begin(), end = m_symbols.end();
pos != end; ++pos) {
const char *name = pos->GetName().AsCString();
if (name && name[0])
name_map.insert(std::make_pair(name, &(*pos)));
}
for (const Symbol &symbol : m_symbols)
name_map.emplace(llvm::StringRef(symbol.GetName()), &symbol);

for (const auto &name_to_symbol : name_map) {
const Symbol *symbol = name_to_symbol.second;
Expand All @@ -138,6 +134,21 @@ void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order,
}
} break;

case eSortOrderBySize: {
s->PutCString(" (sorted by size):\n");
DumpSymbolHeader(s);

std::multimap<size_t, const Symbol *, std::greater<size_t>> size_map;
for (const Symbol &symbol : m_symbols)
size_map.emplace(symbol.GetByteSize(), &symbol);

for (const auto &size_to_symbol : size_map) {
const Symbol *symbol = size_to_symbol.second;
s->Indent();
symbol->Dump(s, target, symbol - &m_symbols[0], name_preference);
}
} break;

case eSortOrderByAddress:
s->PutCString(" (sorted by address):\n");
DumpSymbolHeader(s);
Expand Down
1 change: 0 additions & 1 deletion lldb/test/API/lang/c/local_variables/TestLocalVariables.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ def setUp(self):
self.source = "main.c"
self.line = line_number(self.source, "// Set break point at this line.")

@skipIfWindows
def test_c_local_variables(self):
"""Test local variable value."""
self.build()
Expand Down
4 changes: 4 additions & 0 deletions lldb/test/API/lang/cpp/gmodules/alignment/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
PCH_CXX_SOURCE = pch.h
CXX_SOURCES = main.cpp

include Makefile.rules
60 changes: 60 additions & 0 deletions lldb/test/API/lang/cpp/gmodules/alignment/TestPchAlignment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""
Tests that we correctly track AST layout info
(specifically alignment) when moving AST nodes
between ClangASTImporter instances (in this case,
from pch to executable to expression AST).
"""

import lldb
import os
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil


class TestPchAlignment(TestBase):
@add_test_categories(["gmodules"])
def test_expr(self):
self.build()
lldbutil.run_to_source_breakpoint(
self, "return data", lldb.SBFileSpec("main.cpp")
)

self.expect(
"frame variable data",
substrs=["row = 1", "col = 2", "row = 3", "col = 4", "stride = 5"],
)

@add_test_categories(["gmodules"])
def test_frame_var(self):
self.build()
lldbutil.run_to_source_breakpoint(
self, "return data", lldb.SBFileSpec("main.cpp")
)

self.expect_expr(
"data",
result_type="MatrixData",
result_children=[
ValueCheck(
name="section",
children=[
ValueCheck(
name="origin",
children=[
ValueCheck(name="row", value="1"),
ValueCheck(name="col", value="2"),
],
),
ValueCheck(
name="size",
children=[
ValueCheck(name="row", value="3"),
ValueCheck(name="col", value="4"),
],
),
],
),
ValueCheck(name="stride", value="5"),
],
)
10 changes: 10 additions & 0 deletions lldb/test/API/lang/cpp/gmodules/alignment/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
int main(int argc, const char *argv[]) {
struct MatrixData data = {0};
data.section.origin.row = 1;
data.section.origin.col = 2;
data.section.size.row = 3;
data.section.size.col = 4;
data.stride = 5;

return data.section.size.row;
}
21 changes: 21 additions & 0 deletions lldb/test/API/lang/cpp/gmodules/alignment/pch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef PCH_H_IN
#define PCH_H_IN

static const int kAlignment = 64;

struct [[gnu::aligned(kAlignment)]] RowCol {
unsigned row;
unsigned col;
};

struct [[gnu::aligned(kAlignment)]] Submatrix {
struct RowCol origin;
struct RowCol size;
};

struct [[gnu::aligned(kAlignment)]] MatrixData {
struct Submatrix section;
unsigned stride;
};

#endif // _H_IN
12 changes: 6 additions & 6 deletions lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def test_termination(self):
self.dap_server.request_disconnect()

# Wait until the underlying lldb-dap process dies.
self.dap_server.process.wait(timeout=10)
self.dap_server.process.wait(timeout=lldbdap_testcase.DAPTestCaseBase.timeoutval)

# Check the return code
self.assertEqual(self.dap_server.process.poll(), 0)
Expand Down Expand Up @@ -334,14 +334,14 @@ def test_commands(self):
# Get output from the console. This should contain both the
# "stopCommands" that were run after the first breakpoint was hit
self.continue_to_breakpoints(breakpoint_ids)
output = self.get_console(timeout=1.0)
output = self.get_console(timeout=lldbdap_testcase.DAPTestCaseBase.timeoutval)
self.verify_commands("stopCommands", output, stopCommands)

# Continue again and hit the second breakpoint.
# Get output from the console. This should contain both the
# "stopCommands" that were run after the second breakpoint was hit
self.continue_to_breakpoints(breakpoint_ids)
output = self.get_console(timeout=1.0)
output = self.get_console(timeout=lldbdap_testcase.DAPTestCaseBase.timeoutval)
self.verify_commands("stopCommands", output, stopCommands)

# Continue until the program exits
Expand Down Expand Up @@ -402,21 +402,21 @@ def test_extra_launch_commands(self):
self.verify_commands("launchCommands", output, launchCommands)
# Verify the "stopCommands" here
self.continue_to_next_stop()
output = self.get_console(timeout=1.0)
output = self.get_console(timeout=lldbdap_testcase.DAPTestCaseBase.timeoutval)
self.verify_commands("stopCommands", output, stopCommands)

# Continue and hit the second breakpoint.
# Get output from the console. This should contain both the
# "stopCommands" that were run after the first breakpoint was hit
self.continue_to_next_stop()
output = self.get_console(timeout=1.0)
output = self.get_console(timeout=lldbdap_testcase.DAPTestCaseBase.timeoutval)
self.verify_commands("stopCommands", output, stopCommands)

# Continue until the program exits
self.continue_to_exit()
# Get output from the console. This should contain both the
# "exitCommands" that were run after the second breakpoint was hit
output = self.get_console(timeout=1.0)
output = self.get_console(timeout=lldbdap_testcase.DAPTestCaseBase.timeoutval)
self.verify_commands("exitCommands", output, exitCommands)

@skipIfWindows
Expand Down
12 changes: 8 additions & 4 deletions lldb/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ endif()

if(LLDB_ENFORCE_STRICT_TEST_REQUIREMENTS)
message(STATUS "Enforcing strict test requirements for LLDB")
set(useful_python_modules
psutil # Lit uses psutil to do per-test timeouts.
pexpect # We no longer vendor pexpect.
)
# Lit uses psutil to do per-test timeouts.
set(useful_python_modules psutil)

if(NOT WIN32)
# We no longer vendor pexpect and it is not used on Windows.
list(APPEND pexpect)
endif()

foreach(module ${useful_python_modules})
lldb_find_python_module(${module})
if (NOT PY_${module}_FOUND)
Expand Down
11 changes: 11 additions & 0 deletions lldb/test/Shell/SymbolFile/Breakpad/symtab-sorted-by-size.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %T/symtab.out
# RUN: %lldb %T/symtab.out -o "target symbols add -s symtab.out %S/Inputs/symtab.syms" \
# RUN: -s %s | FileCheck %s

# CHECK: num_symbols = 4 (sorted by size):
# CHECK: [ 0] 0 SX Code 0x0000000000400000 0x00000000000000b0 0x00000000 ___lldb_unnamed_symbol0
# CHECK: [ 3] 0 X Code 0x00000000004000d0 0x0000000000000022 0x00000000 _start
# CHECK: [ 1] 0 X Code 0x00000000004000b0 0x0000000000000010 0x00000000 f1
# CHECK: [ 2] 0 X Code 0x00000000004000c0 0x0000000000000010 0x00000000 f2

image dump symtab -s size symtab.out
319 changes: 159 additions & 160 deletions lldb/tools/debugserver/source/RNBRemote.cpp

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions lldb/tools/debugserver/source/RNBRemote.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ enum class compression_types { zlib_deflate, lz4, lzma, lzfse, none };

class RNBRemote {
public:
// clang-format off
enum PacketEnum {
invalid_packet = 0,
ack, // '+'
Expand Down Expand Up @@ -137,8 +138,10 @@ class RNBRemote {
set_detach_on_error, // 'QSetDetachOnError:'
query_transfer, // 'qXfer:'
json_query_dyld_process_state, // 'jGetDyldProcessState'
enable_error_strings, // 'QEnableErrorStrings'
unknown_type
};
// clang-format on

typedef rnb_err_t (RNBRemote::*HandlePacketCallback)(const char *p);

Expand Down Expand Up @@ -196,6 +199,7 @@ class RNBRemote {
rnb_err_t HandlePacket_qGDBServerVersion(const char *p);
rnb_err_t HandlePacket_qProcessInfo(const char *p);
rnb_err_t HandlePacket_qSymbol(const char *p);
rnb_err_t HandlePacket_QEnableErrorStrings(const char *p);
rnb_err_t HandlePacket_QStartNoAckMode(const char *p);
rnb_err_t HandlePacket_QThreadSuffixSupported(const char *p);
rnb_err_t HandlePacket_QSetLogging(const char *p);
Expand Down Expand Up @@ -356,6 +360,8 @@ class RNBRemote {
rnb_err_t GetPacket(std::string &packet_data, RNBRemote::Packet &packet_info,
bool wait);
rnb_err_t SendPacket(const std::string &);
rnb_err_t SendErrorPacket(std::string errcode,
const std::string &errmsg = "");
std::string CompressString(const std::string &);

void CreatePacketTable();
Expand Down Expand Up @@ -405,6 +411,9 @@ class RNBRemote {
bool m_enable_compression_next_send_packet;

compression_types m_compression_mode;

bool m_enable_error_strings; // Whether we can append asciihex error strings
// after Exx error replies
};

/* We translate the /usr/include/mach/exception_types.h exception types
Expand Down
11 changes: 11 additions & 0 deletions llvm/docs/CodeOfConduct.rst
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,17 @@ events as part of each events' information. In person reports will still be
kept confidential exactly as above, but also feel free to (anonymously if
needed) email conduct@llvm.org.

Bans
====

The code of conduct committee may decide to ban an individual from the
community for violating the code of conduct. The goal of a ban is to protect
community members from having to interact with people who are consistently not
respecting the code of conduct. Please refer to the
:doc:`Developer Policy<DeveloperPolicy>` section on Bans for how to handle
interactions with former community members. If you need further guidance,
please contact conduct@llvm.org.

Code of Conduct Committee
=========================

Expand Down
14 changes: 10 additions & 4 deletions llvm/docs/CommandGuide/llvm-readobj.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ file formats.
Dump decompressed section content when used with ``-x`` or ``-p``.
If the section(s) are not compressed, they are displayed as is.

.. option:: --demangle, -C

Display demangled symbol names in the output. This option is only for ELF and
XCOFF file formats.

.. option:: --expand-relocs

When used with :option:`--relocs`, display each relocation in an expanded
Expand Down Expand Up @@ -94,6 +99,11 @@ file formats.

Display the needed libraries.

.. option:: --no-demangle

Do not demangle symbol names in the output. This option is only for ELF and
XCOFF file formats. The option is enabled by default.

.. option:: --relocations, --relocs, -r

Display the relocation entries in the file.
Expand Down Expand Up @@ -175,10 +185,6 @@ The following options are implemented only for the ELF file format.

Requires :option:`--bb-addr-map` to have an effect.

.. option:: --demangle, -C

Display demangled symbol names in the output.

.. option:: --dependent-libraries

Display the dependent libraries section.
Expand Down
5 changes: 0 additions & 5 deletions llvm/include/llvm/ADT/SmallString.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,6 @@ class SmallString : public SmallVector<char, InternalLen> {
/// Implicit conversion to StringRef.
operator StringRef() const { return str(); }

/// Implicit conversion to std::string_view.
operator std::string_view() const {
return std::string_view(this->data(), this->size());
}

explicit operator std::string() const {
return std::string(this->data(), this->size());
}
Expand Down
12 changes: 0 additions & 12 deletions llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -908,18 +908,6 @@ class LegalizeRuleSet {
LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize));
}

/// Widen the scalar or vector element type to the next power of two that is
/// at least MinSize. No effect if the scalar size is a power of two.
LegalizeRuleSet &widenScalarOrEltToNextPow2OrMinSize(unsigned TypeIdx,
unsigned MinSize = 0) {
using namespace LegalityPredicates;
return actionIf(
LegalizeAction::WidenScalar,
any(scalarOrEltNarrowerThan(TypeIdx, MinSize),
scalarOrEltSizeNotPow2(typeIdx(TypeIdx))),
LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize));
}

LegalizeRuleSet &narrowScalar(unsigned TypeIdx, LegalizeMutation Mutation) {
using namespace LegalityPredicates;
return actionIf(LegalizeAction::NarrowScalar, isScalar(typeIdx(TypeIdx)),
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/IR/Intrinsics.td
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@ def llvm_v1i32_ty : LLVMType<v1i32>; // 1 x i32
def llvm_v2i32_ty : LLVMType<v2i32>; // 2 x i32
def llvm_v3i32_ty : LLVMType<v3i32>; // 3 x i32
def llvm_v4i32_ty : LLVMType<v4i32>; // 4 x i32
def llvm_v6i32_ty : LLVMType<v6i32>; // 6 x i32
def llvm_v8i32_ty : LLVMType<v8i32>; // 8 x i32
def llvm_v16i32_ty : LLVMType<v16i32>; // 16 x i32
def llvm_v32i32_ty : LLVMType<v32i32>; // 32 x i32
Expand Down
7 changes: 7 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsAMDGPU.td
Original file line number Diff line number Diff line change
Expand Up @@ -3196,4 +3196,11 @@ def int_amdgcn_fdiv_fast : DefaultAttrsIntrinsic<
[llvm_float_ty], [llvm_float_ty, llvm_float_ty],
[IntrNoMem, IntrSpeculatable]
>;

/// Emit an addrspacecast without null pointer checking.
/// Should only be inserted by a pass based on analysis of an addrspacecast's src.
def int_amdgcn_addrspacecast_nonnull : DefaultAttrsIntrinsic<
[llvm_anyptr_ty], [llvm_anyptr_ty],
[IntrNoMem, IntrSpeculatable]
>;
}
23 changes: 8 additions & 15 deletions llvm/include/llvm/IR/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,30 +385,23 @@ class LLVM_EXTERNAL_VISIBILITY Module {
/// @name Function Accessors
/// @{

/// Look up the specified function in the module symbol table. Four
/// possibilities:
/// 1. If it does not exist, add a prototype for the function and return it.
/// 2. Otherwise, if the existing function has the correct prototype, return
/// the existing function.
/// 3. Finally, the function exists but has the wrong prototype: return the
/// function with a constantexpr cast to the right prototype.
/// Look up the specified function in the module symbol table. If it does not
/// exist, add a prototype for the function and return it. Otherwise, return
/// the existing function.
///
/// In all cases, the returned value is a FunctionCallee wrapper around the
/// 'FunctionType *T' passed in, as well as a 'Value*' either of the Function or
/// the bitcast to the function.
/// 'FunctionType *T' passed in, as well as the 'Value*' of the Function. The
/// function type of the function may differ from the function type stored in
/// FunctionCallee if it was previously created with a different type.
///
/// Note: For library calls getOrInsertLibFunc() should be used instead.
FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T,
AttributeList AttributeList);

FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T);

/// Look up the specified function in the module symbol table. If it does not
/// exist, add a prototype for the function and return it. This function
/// guarantees to return a constant of pointer to the specified function type
/// or a ConstantExpr BitCast of that type if the named function has a
/// different type. This version of the method takes a list of
/// function arguments, which makes it easier for clients to use.
/// Same as above, but takes a list of function arguments, which makes it
/// easier for clients to use.
template <typename... ArgsTy>
FunctionCallee getOrInsertFunction(StringRef Name,
AttributeList AttributeList, Type *RetTy,
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/MC/MCExpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ class MCSymbolRefExpr : public MCExpr {
VK_PPC_AIX_TLSGDM, // symbol@m
VK_PPC_AIX_TLSIE, // symbol@ie
VK_PPC_AIX_TLSLE, // symbol@le
VK_PPC_AIX_TLSLD, // symbol@ld
VK_PPC_AIX_TLSML, // symbol@ml
VK_PPC_GOT_TLSLD, // symbol@got@tlsld
VK_PPC_GOT_TLSLD_LO, // symbol@got@tlsld@l
VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/TargetParser/RISCVTargetParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ namespace RISCV {
// We use 64 bits as the known part in the scalable vector types.
static constexpr unsigned RVVBitsPerBlock = 64;

void getFeaturesForCPU(StringRef CPU,
SmallVectorImpl<std::string> &EnabledFeatures,
bool NeedPlus = false);
bool parseCPU(StringRef CPU, bool IsRV64);
bool parseTuneCPU(StringRef CPU, bool IsRV64);
StringRef getMArchFromMcpu(StringRef CPU);
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/TextAPI/Record.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ class ObjCCategoryRecord : public ObjCContainerRecord {
: ObjCContainerRecord(Name, RecordLinkage::Unknown),
ClassToExtend(ClassToExtend) {}

StringRef getSuperClassName() const { return ClassToExtend; }

private:
StringRef ClassToExtend;
};
Expand Down
1 change: 0 additions & 1 deletion llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2495,7 +2495,6 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
case TargetOpcode::G_OR:
case TargetOpcode::G_XOR:
case TargetOpcode::G_SUB:
case TargetOpcode::G_SHUFFLE_VECTOR:
// Perform operation at larger width (any extension is fines here, high bits
// don't affect the result) and then truncate the result back to the
// original type.
Expand Down
23 changes: 18 additions & 5 deletions llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2418,6 +2418,15 @@ MCSection *TargetLoweringObjectFileXCOFF::getSectionForExternalReference(
SmallString<128> Name;
getNameWithPrefix(Name, GO, TM);

// AIX TLS local-dynamic does not need the external reference for the
// "_$TLSML" symbol.
if (GO->getThreadLocalMode() == GlobalVariable::LocalDynamicTLSModel &&
GO->hasName() && GO->getName() == "_$TLSML") {
return getContext().getXCOFFSection(
Name, SectionKind::getData(),
XCOFF::CsectProperties(XCOFF::XMC_TC, XCOFF::XTY_SD));
}

XCOFF::StorageMappingClass SMC =
isa<Function>(GO) ? XCOFF::XMC_DS : XCOFF::XMC_UA;
if (GO->isThreadLocal())
Expand Down Expand Up @@ -2675,13 +2684,17 @@ MCSection *TargetLoweringObjectFileXCOFF::getSectionForTOCEntry(
// the chance of needing -bbigtoc is decreased. Also, the toc-entry for
// EH info is never referenced directly using instructions so it can be
// allocated with TE storage-mapping class.
// The "_$TLSML" symbol for TLS local-dynamic mode requires XMC_TC, otherwise
// the AIX assembler will complain.
return getContext().getXCOFFSection(
cast<MCSymbolXCOFF>(Sym)->getSymbolTableName(), SectionKind::getData(),
XCOFF::CsectProperties((TM.getCodeModel() == CodeModel::Large ||
cast<MCSymbolXCOFF>(Sym)->isEHInfo())
? XCOFF::XMC_TE
: XCOFF::XMC_TC,
XCOFF::XTY_SD));
XCOFF::CsectProperties(
((TM.getCodeModel() == CodeModel::Large &&
cast<MCSymbolXCOFF>(Sym)->getSymbolTableName() != "_$TLSML") ||
cast<MCSymbolXCOFF>(Sym)->isEHInfo())
? XCOFF::XMC_TE
: XCOFF::XMC_TC,
XCOFF::XTY_SD));
}

MCSection *TargetLoweringObjectFileXCOFF::getSectionForLSDA(
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/MC/MCExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,10 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
return "ie";
case VK_PPC_AIX_TLSLE:
return "le";
case VK_PPC_AIX_TLSLD:
return "ld";
case VK_PPC_AIX_TLSML:
return "ml";
case VK_PPC_GOT_TLSLD: return "got@tlsld";
case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l";
case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h";
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/MC/XCOFFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,8 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
if (Type == XCOFF::RelocationType::R_POS ||
Type == XCOFF::RelocationType::R_TLS ||
Type == XCOFF::RelocationType::R_TLS_LE ||
Type == XCOFF::RelocationType::R_TLS_IE)
Type == XCOFF::RelocationType::R_TLS_IE ||
Type == XCOFF::RelocationType::R_TLS_LD)
// The FixedValue should be symbol's virtual address in this object file
// plus any constant value that we might get.
FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();
Expand Down
21 changes: 17 additions & 4 deletions llvm/lib/Passes/PassBuilderPipelines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,15 @@ static cl::opt<bool> EnableLoopFlatten("enable-loop-flatten", cl::init(false),
cl::Hidden,
cl::desc("Enable the LoopFlatten Pass"));

// Experimentally allow loop header duplication. This should allow for better
// optimization at Oz, since loop-idiom recognition can then recognize things
// like memcpy. If this ends up being useful for many targets, we should drop
// this flag and make a code generation option that can be controlled
// independent of the opt level and exposed through the frontend.
static cl::opt<bool> EnableLoopHeaderDuplication(
"enable-loop-header-duplication", cl::init(false), cl::Hidden,
cl::desc("Enable loop header duplication at any optimization level"));

static cl::opt<bool>
EnableDFAJumpThreading("enable-dfa-jump-thread",
cl::desc("Enable DFA jump threading"),
Expand Down Expand Up @@ -630,8 +639,9 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
/*AllowSpeculation=*/false));

// Disable header duplication in loop rotation at -Oz.
LPM1.addPass(
LoopRotatePass(Level != OptimizationLevel::Oz, isLTOPreLink(Phase)));
LPM1.addPass(LoopRotatePass(EnableLoopHeaderDuplication ||
Level != OptimizationLevel::Oz,
isLTOPreLink(Phase)));
// TODO: Investigate promotion cap for O1.
LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap,
/*AllowSpeculation=*/true));
Expand Down Expand Up @@ -812,7 +822,8 @@ void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM,
// Disable header duplication in loop rotation at -Oz.
MPM.addPass(createModuleToFunctionPassAdaptor(
createFunctionToLoopPassAdaptor(
LoopRotatePass(Level != OptimizationLevel::Oz),
LoopRotatePass(EnableLoopHeaderDuplication ||
Level != OptimizationLevel::Oz),
/*UseMemorySSA=*/false,
/*UseBlockFrequencyInfo=*/false),
PTO.EagerlyInvalidateAnalyses));
Expand Down Expand Up @@ -1422,7 +1433,9 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
LoopPassManager LPM;
// First rotate loops that may have been un-rotated by prior passes.
// Disable header duplication at -Oz.
LPM.addPass(LoopRotatePass(Level != OptimizationLevel::Oz, LTOPreLink));
LPM.addPass(LoopRotatePass(EnableLoopHeaderDuplication ||
Level != OptimizationLevel::Oz,
LTOPreLink));
// Some loops may have become dead by now. Try to delete them.
// FIXME: see discussion in https://reviews.llvm.org/D112851,
// this may need to be revisited once we run GVN before loop deletion
Expand Down
1 change: 0 additions & 1 deletion llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2547,7 +2547,6 @@ const char *AArch64TargetLowering::getTargetNodeName(unsigned Opcode) const {
MAKE_CASE(AArch64ISD::FSUB_PRED)
MAKE_CASE(AArch64ISD::RDSVL)
MAKE_CASE(AArch64ISD::BIC)
MAKE_CASE(AArch64ISD::BIT)
MAKE_CASE(AArch64ISD::CBZ)
MAKE_CASE(AArch64ISD::CBNZ)
MAKE_CASE(AArch64ISD::TBZ)
Expand Down
3 changes: 0 additions & 3 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,6 @@ enum NodeType : unsigned {
EORV_PRED,
ANDV_PRED,

// Vector bitwise insertion
BIT,

// Compare-and-branch
CBZ,
CBNZ,
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/Target/AArch64/AArch64InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,6 @@ def AArch64urshri : SDNode<"AArch64ISD::URSHR_I", SDT_AArch64vshift>;
def AArch64vsli : SDNode<"AArch64ISD::VSLI", SDT_AArch64vshiftinsert>;
def AArch64vsri : SDNode<"AArch64ISD::VSRI", SDT_AArch64vshiftinsert>;

def AArch64bit: SDNode<"AArch64ISD::BIT", SDT_AArch64trivec>;
def AArch64bsp: SDNode<"AArch64ISD::BSP", SDT_AArch64trivec>;

def AArch64cmeq: SDNode<"AArch64ISD::CMEQ", SDT_AArch64binvec>;
Expand Down Expand Up @@ -5333,7 +5332,7 @@ defm ORR : SIMDLogicalThreeVector<0, 0b10, "orr", or>;
defm BSP : SIMDLogicalThreeVectorPseudo<TriOpFrag<(or (and node:$LHS, node:$MHS),
(and (vnot node:$LHS), node:$RHS))>>;
defm BSL : SIMDLogicalThreeVectorTied<1, 0b01, "bsl">;
defm BIT : SIMDLogicalThreeVectorTied<1, 0b10, "bit", AArch64bit>;
defm BIT : SIMDLogicalThreeVectorTied<1, 0b10, "bit">;
defm BIF : SIMDLogicalThreeVectorTied<1, 0b11, "bif">;

def : Pat<(AArch64bsp (v8i8 V64:$Rd), V64:$Rn, V64:$Rm),
Expand Down Expand Up @@ -8216,8 +8215,10 @@ defm ST4 : SIMDLdSt4SingleAliases<"st4">;
//----------------------------------------------------------------------------

let Predicates = [HasAES] in {
let isCommutable = 1 in {
def AESErr : AESTiedInst<0b0100, "aese", int_aarch64_crypto_aese>;
def AESDrr : AESTiedInst<0b0101, "aesd", int_aarch64_crypto_aesd>;
}
def AESMCrr : AESInst< 0b0110, "aesmc", int_aarch64_crypto_aesmc>;
def AESIMCrr : AESInst< 0b0111, "aesimc", int_aarch64_crypto_aesimc>;
}
Expand Down
9 changes: 6 additions & 3 deletions llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -956,9 +956,6 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
},
changeTo(1, 0))
.moreElementsToNextPow2(0)
.widenScalarOrEltToNextPow2OrMinSize(0, 8)
.clampNumElements(0, v8s8, v16s8)
.clampNumElements(0, v4s16, v8s16)
.clampNumElements(0, v4s32, v4s32)
.clampNumElements(0, v2s64, v2s64)
.moreElementsIf(
Expand Down Expand Up @@ -1009,6 +1006,12 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
ABSActions
.legalFor({s32, s64});
ABSActions.legalFor(PackedVectorAllTypeList)
.widenScalarIf(
[=](const LegalityQuery &Query) { return Query.Types[0] == v4s8; },
[=](const LegalityQuery &Query) { return std::make_pair(0, v4s16); })
.widenScalarIf(
[=](const LegalityQuery &Query) { return Query.Types[0] == v2s16; },
[=](const LegalityQuery &Query) { return std::make_pair(0, v2s32); })
.clampNumElements(0, v8s8, v16s8)
.clampNumElements(0, v4s16, v8s16)
.clampNumElements(0, v2s32, v4s32)
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/AMDGPU/AMDGPUCallingConv.td
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ def RetCC_SI_Gfx : CallingConv<[

def CC_SI_SHADER : CallingConv<[

CCIfType<[i1], CCPromoteToType<i32>>,

CCIfInReg<CCIfType<[f32, i32, f16, i16, v2i16, v2f16, bf16, v2bf16] , CCAssignToReg<[
SGPR0, SGPR1, SGPR2, SGPR3, SGPR4, SGPR5, SGPR6, SGPR7,
SGPR8, SGPR9, SGPR10, SGPR11, SGPR12, SGPR13, SGPR14, SGPR15,
Expand Down
73 changes: 73 additions & 0 deletions llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class AMDGPUCodeGenPrepareImpl
: public InstVisitor<AMDGPUCodeGenPrepareImpl, bool> {
public:
const GCNSubtarget *ST = nullptr;
const AMDGPUTargetMachine *TM = nullptr;
const TargetLibraryInfo *TLInfo = nullptr;
AssumptionCache *AC = nullptr;
DominatorTree *DT = nullptr;
Expand Down Expand Up @@ -310,6 +311,7 @@ class AMDGPUCodeGenPrepareImpl
bool visitICmpInst(ICmpInst &I);
bool visitSelectInst(SelectInst &I);
bool visitPHINode(PHINode &I);
bool visitAddrSpaceCastInst(AddrSpaceCastInst &I);

bool visitIntrinsicInst(IntrinsicInst &I);
bool visitBitreverseIntrinsicInst(IntrinsicInst &I);
Expand Down Expand Up @@ -2013,6 +2015,75 @@ bool AMDGPUCodeGenPrepareImpl::visitPHINode(PHINode &I) {
return true;
}

/// \param V Value to check
/// \param DL DataLayout
/// \param TM TargetMachine (TODO: remove once DL contains nullptr values)
/// \param AS Target Address Space
/// \return true if \p V cannot be the null value of \p AS, false otherwise.
static bool isPtrKnownNeverNull(const Value *V, const DataLayout &DL,
const AMDGPUTargetMachine &TM, unsigned AS) {
// Pointer cannot be null if it's a block address, GV or alloca.
// NOTE: We don't support extern_weak, but if we did, we'd need to check for
// it as the symbol could be null in such cases.
if (isa<BlockAddress>(V) || isa<GlobalValue>(V) || isa<AllocaInst>(V))
return true;

// Check nonnull arguments.
if (const auto *Arg = dyn_cast<Argument>(V); Arg && Arg->hasNonNullAttr())
return true;

// TODO: Calls that return nonnull?

// For all other things, use KnownBits.
// We either use 0 or all bits set to indicate null, so check whether the
// value can be zero or all ones.
//
// TODO: Use ValueTracking's isKnownNeverNull if it becomes aware that some
// address spaces have non-zero null values.
auto SrcPtrKB = computeKnownBits(V, DL).trunc(DL.getPointerSizeInBits(AS));
const auto NullVal = TM.getNullPointerValue(AS);
assert((NullVal == 0 || NullVal == -1) &&
"don't know how to check for this null value!");
return NullVal ? !SrcPtrKB.getMaxValue().isAllOnes() : SrcPtrKB.isNonZero();
}

bool AMDGPUCodeGenPrepareImpl::visitAddrSpaceCastInst(AddrSpaceCastInst &I) {
// Intrinsic doesn't support vectors, also it seems that it's often difficult
// to prove that a vector cannot have any nulls in it so it's unclear if it's
// worth supporting.
if (I.getType()->isVectorTy())
return false;

// Check if this can be lowered to a amdgcn.addrspacecast.nonnull.
// This is only worthwhile for casts from/to priv/local to flat.
const unsigned SrcAS = I.getSrcAddressSpace();
const unsigned DstAS = I.getDestAddressSpace();

bool CanLower = false;
if (SrcAS == AMDGPUAS::FLAT_ADDRESS)
CanLower = (DstAS == AMDGPUAS::LOCAL_ADDRESS ||
DstAS == AMDGPUAS::PRIVATE_ADDRESS);
else if (DstAS == AMDGPUAS::FLAT_ADDRESS)
CanLower = (SrcAS == AMDGPUAS::LOCAL_ADDRESS ||
SrcAS == AMDGPUAS::PRIVATE_ADDRESS);
if (!CanLower)
return false;

SmallVector<const Value *, 4> WorkList;
getUnderlyingObjects(I.getOperand(0), WorkList);
if (!all_of(WorkList, [&](const Value *V) {
return isPtrKnownNeverNull(V, *DL, *TM, SrcAS);
}))
return false;

IRBuilder<> B(&I);
auto *Intrin = B.CreateIntrinsic(
I.getType(), Intrinsic::amdgcn_addrspacecast_nonnull, {I.getOperand(0)});
I.replaceAllUsesWith(Intrin);
I.eraseFromParent();
return true;
}

bool AMDGPUCodeGenPrepareImpl::visitIntrinsicInst(IntrinsicInst &I) {
switch (I.getIntrinsicID()) {
case Intrinsic::bitreverse:
Expand Down Expand Up @@ -2196,6 +2267,7 @@ bool AMDGPUCodeGenPrepare::runOnFunction(Function &F) {
return false;

const AMDGPUTargetMachine &TM = TPC->getTM<AMDGPUTargetMachine>();
Impl.TM = &TM;
Impl.TLInfo = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
Impl.ST = &TM.getSubtarget<GCNSubtarget>(F);
Impl.AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
Expand All @@ -2214,6 +2286,7 @@ PreservedAnalyses AMDGPUCodeGenPreparePass::run(Function &F,
AMDGPUCodeGenPrepareImpl Impl;
Impl.Mod = F.getParent();
Impl.DL = &Impl.Mod->getDataLayout();
Impl.TM = static_cast<const AMDGPUTargetMachine *>(&TM);
Impl.TLInfo = &FAM.getResult<TargetLibraryAnalysis>(F);
Impl.ST = &TM.getSubtarget<GCNSubtarget>(F);
Impl.AC = &FAM.getResult<AssumptionAnalysis>(F);
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/AMDGPU/AMDGPUGenRegisterBankInfo.def
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ const RegisterBankInfo::ValueMapping *getValueMapping(unsigned BankID,
break;
}

assert(Idx < std::size(ValMappings));
assert(Log2_32_Ceil(Size) == Log2_32_Ceil(ValMappings[Idx].BreakDown->Length));
assert(BankID == ValMappings[Idx].BreakDown->RegBank->getID());

Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3089,10 +3089,10 @@ SDValue AMDGPUTargetLowering::lowerCTLZResults(SDValue Op,
assert(ResultVT == Arg.getValueType());

auto const LeadingZeroes = 32u - ResultVT.getFixedSizeInBits();
auto SubVal = DAG.getConstant(LeadingZeroes, SL, MVT::i32);
auto NewOp = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Arg);
auto ShiftVal = DAG.getConstant(LeadingZeroes, SL, MVT::i32);
NewOp = DAG.getNode(ISD::SHL, SL, MVT::i32, NewOp, ShiftVal);
NewOp = DAG.getNode(Op.getOpcode(), SL, MVT::i32, NewOp);
NewOp = DAG.getNode(ISD::SUB, SL, MVT::i32, NewOp, SubVal);
return DAG.getNode(ISD::TRUNCATE, SL, ResultVT, NewOp);
}

Expand Down
Loading