From c5b11a710e01304908e3f320e40bc9da9f6a8de4 Mon Sep 17 00:00:00 2001 From: Alex MacLean Date: Sat, 18 May 2024 10:33:05 -0700 Subject: [PATCH 001/793] [NVPTX] support immediate values in st.param instructions (#91523) Add support for generating `st.param` instructions with direct use of immediates. This eliminates the need for a `mov` instruction prior to the `st.param` resulting in more concise emitted PTX. --- llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp | 161 +- llvm/lib/Target/NVPTX/NVPTXInstrInfo.td | 100 +- llvm/test/CodeGen/NVPTX/st-param-imm.ll | 2002 +++++++++++++++++++ 3 files changed, 2199 insertions(+), 64 deletions(-) create mode 100644 llvm/test/CodeGen/NVPTX/st-param-imm.ll diff --git a/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp b/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp index 595395bb1b4b..2713b6859ff3 100644 --- a/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp @@ -2182,6 +2182,100 @@ bool NVPTXDAGToDAGISel::tryStoreRetval(SDNode *N) { return true; } +// Helpers for constructing opcode (ex: NVPTX::StoreParamV4F32_iiri) +#define getOpcV2H(ty, opKind0, opKind1) \ + NVPTX::StoreParamV2##ty##_##opKind0##opKind1 + +#define getOpcV2H1(ty, opKind0, isImm1) \ + (isImm1) ? getOpcV2H(ty, opKind0, i) : getOpcV2H(ty, opKind0, r) + +#define getOpcodeForVectorStParamV2(ty, isimm) \ + (isimm[0]) ? getOpcV2H1(ty, i, isimm[1]) : getOpcV2H1(ty, r, isimm[1]) + +#define getOpcV4H(ty, opKind0, opKind1, opKind2, opKind3) \ + NVPTX::StoreParamV4##ty##_##opKind0##opKind1##opKind2##opKind3 + +#define getOpcV4H3(ty, opKind0, opKind1, opKind2, isImm3) \ + (isImm3) ? getOpcV4H(ty, opKind0, opKind1, opKind2, i) \ + : getOpcV4H(ty, opKind0, opKind1, opKind2, r) + +#define getOpcV4H2(ty, opKind0, opKind1, isImm2, isImm3) \ + (isImm2) ? getOpcV4H3(ty, opKind0, opKind1, i, isImm3) \ + : getOpcV4H3(ty, opKind0, opKind1, r, isImm3) + +#define getOpcV4H1(ty, opKind0, isImm1, isImm2, isImm3) \ + (isImm1) ? getOpcV4H2(ty, opKind0, i, isImm2, isImm3) \ + : getOpcV4H2(ty, opKind0, r, isImm2, isImm3) + +#define getOpcodeForVectorStParamV4(ty, isimm) \ + (isimm[0]) ? getOpcV4H1(ty, i, isimm[1], isimm[2], isimm[3]) \ + : getOpcV4H1(ty, r, isimm[1], isimm[2], isimm[3]) + +#define getOpcodeForVectorStParam(n, ty, isimm) \ + (n == 2) ? getOpcodeForVectorStParamV2(ty, isimm) \ + : getOpcodeForVectorStParamV4(ty, isimm) + +static unsigned pickOpcodeForVectorStParam(SmallVector &Ops, + unsigned NumElts, + MVT::SimpleValueType MemTy, + SelectionDAG *CurDAG, SDLoc DL) { + // Determine which inputs are registers and immediates make new operators + // with constant values + SmallVector IsImm(NumElts, false); + for (unsigned i = 0; i < NumElts; i++) { + IsImm[i] = (isa(Ops[i]) || isa(Ops[i])); + if (IsImm[i]) { + SDValue Imm = Ops[i]; + if (MemTy == MVT::f32 || MemTy == MVT::f64) { + const ConstantFPSDNode *ConstImm = cast(Imm); + const ConstantFP *CF = ConstImm->getConstantFPValue(); + Imm = CurDAG->getTargetConstantFP(*CF, DL, Imm->getValueType(0)); + } else { + const ConstantSDNode *ConstImm = cast(Imm); + const ConstantInt *CI = ConstImm->getConstantIntValue(); + Imm = CurDAG->getTargetConstant(*CI, DL, Imm->getValueType(0)); + } + Ops[i] = Imm; + } + } + + // Get opcode for MemTy, size, and register/immediate operand ordering + switch (MemTy) { + case MVT::i8: + return getOpcodeForVectorStParam(NumElts, I8, IsImm); + case MVT::i16: + return getOpcodeForVectorStParam(NumElts, I16, IsImm); + case MVT::i32: + return getOpcodeForVectorStParam(NumElts, I32, IsImm); + case MVT::i64: + assert(NumElts == 2 && "MVT too large for NumElts > 2"); + return getOpcodeForVectorStParamV2(I64, IsImm); + case MVT::f32: + return getOpcodeForVectorStParam(NumElts, F32, IsImm); + case MVT::f64: + assert(NumElts == 2 && "MVT too large for NumElts > 2"); + return getOpcodeForVectorStParamV2(F64, IsImm); + + // These cases don't support immediates, just use the all register version + // and generate moves. + case MVT::i1: + return (NumElts == 2) ? NVPTX::StoreParamV2I8_rr + : NVPTX::StoreParamV4I8_rrrr; + case MVT::f16: + case MVT::bf16: + return (NumElts == 2) ? NVPTX::StoreParamV2I16_rr + : NVPTX::StoreParamV4I16_rrrr; + case MVT::v2f16: + case MVT::v2bf16: + case MVT::v2i16: + case MVT::v4i8: + return (NumElts == 2) ? NVPTX::StoreParamV2I32_rr + : NVPTX::StoreParamV4I32_rrrr; + default: + llvm_unreachable("Cannot select st.param for unknown MemTy"); + } +} + bool NVPTXDAGToDAGISel::tryStoreParam(SDNode *N) { SDLoc DL(N); SDValue Chain = N->getOperand(0); @@ -2193,10 +2287,10 @@ bool NVPTXDAGToDAGISel::tryStoreParam(SDNode *N) { SDValue Glue = N->getOperand(N->getNumOperands() - 1); // How many elements do we have? - unsigned NumElts = 1; + unsigned NumElts; switch (N->getOpcode()) { default: - return false; + llvm_unreachable("Unexpected opcode"); case NVPTXISD::StoreParamU32: case NVPTXISD::StoreParamS32: case NVPTXISD::StoreParam: @@ -2222,18 +2316,40 @@ bool NVPTXDAGToDAGISel::tryStoreParam(SDNode *N) { // Determine target opcode // If we have an i1, use an 8-bit store. The lowering code in // NVPTXISelLowering will have already emitted an upcast. - std::optional Opcode = 0; + std::optional Opcode; switch (N->getOpcode()) { default: switch (NumElts) { default: - return false; - case 1: - Opcode = pickOpcodeForVT(Mem->getMemoryVT().getSimpleVT().SimpleTy, - NVPTX::StoreParamI8, NVPTX::StoreParamI16, - NVPTX::StoreParamI32, NVPTX::StoreParamI64, - NVPTX::StoreParamF32, NVPTX::StoreParamF64); - if (Opcode == NVPTX::StoreParamI8) { + llvm_unreachable("Unexpected NumElts"); + case 1: { + MVT::SimpleValueType MemTy = Mem->getMemoryVT().getSimpleVT().SimpleTy; + SDValue Imm = Ops[0]; + if (MemTy != MVT::f16 && MemTy != MVT::v2f16 && + (isa(Imm) || isa(Imm))) { + // Convert immediate to target constant + if (MemTy == MVT::f32 || MemTy == MVT::f64) { + const ConstantFPSDNode *ConstImm = cast(Imm); + const ConstantFP *CF = ConstImm->getConstantFPValue(); + Imm = CurDAG->getTargetConstantFP(*CF, DL, Imm->getValueType(0)); + } else { + const ConstantSDNode *ConstImm = cast(Imm); + const ConstantInt *CI = ConstImm->getConstantIntValue(); + Imm = CurDAG->getTargetConstant(*CI, DL, Imm->getValueType(0)); + } + Ops[0] = Imm; + // Use immediate version of store param + Opcode = pickOpcodeForVT(MemTy, NVPTX::StoreParamI8_i, + NVPTX::StoreParamI16_i, NVPTX::StoreParamI32_i, + NVPTX::StoreParamI64_i, NVPTX::StoreParamF32_i, + NVPTX::StoreParamF64_i); + } else + Opcode = + pickOpcodeForVT(Mem->getMemoryVT().getSimpleVT().SimpleTy, + NVPTX::StoreParamI8_r, NVPTX::StoreParamI16_r, + NVPTX::StoreParamI32_r, NVPTX::StoreParamI64_r, + NVPTX::StoreParamF32_r, NVPTX::StoreParamF64_r); + if (Opcode == NVPTX::StoreParamI8_r) { // Fine tune the opcode depending on the size of the operand. // This helps to avoid creating redundant COPY instructions in // InstrEmitter::AddRegisterOperand(). @@ -2241,35 +2357,28 @@ bool NVPTXDAGToDAGISel::tryStoreParam(SDNode *N) { default: break; case MVT::i32: - Opcode = NVPTX::StoreParamI8TruncI32; + Opcode = NVPTX::StoreParamI8TruncI32_r; break; case MVT::i64: - Opcode = NVPTX::StoreParamI8TruncI64; + Opcode = NVPTX::StoreParamI8TruncI64_r; break; } } break; + } case 2: - Opcode = pickOpcodeForVT(Mem->getMemoryVT().getSimpleVT().SimpleTy, - NVPTX::StoreParamV2I8, NVPTX::StoreParamV2I16, - NVPTX::StoreParamV2I32, NVPTX::StoreParamV2I64, - NVPTX::StoreParamV2F32, NVPTX::StoreParamV2F64); - break; - case 4: - Opcode = pickOpcodeForVT(Mem->getMemoryVT().getSimpleVT().SimpleTy, - NVPTX::StoreParamV4I8, NVPTX::StoreParamV4I16, - NVPTX::StoreParamV4I32, std::nullopt, - NVPTX::StoreParamV4F32, std::nullopt); + case 4: { + MVT::SimpleValueType MemTy = Mem->getMemoryVT().getSimpleVT().SimpleTy; + Opcode = pickOpcodeForVectorStParam(Ops, NumElts, MemTy, CurDAG, DL); break; } - if (!Opcode) - return false; + } break; // Special case: if we have a sign-extend/zero-extend node, insert the // conversion instruction first, and use that as the value operand to // the selected StoreParam node. case NVPTXISD::StoreParamU32: { - Opcode = NVPTX::StoreParamI32; + Opcode = NVPTX::StoreParamI32_r; SDValue CvtNone = CurDAG->getTargetConstant(NVPTX::PTXCvtMode::NONE, DL, MVT::i32); SDNode *Cvt = CurDAG->getMachineNode(NVPTX::CVT_u32_u16, DL, @@ -2278,7 +2387,7 @@ bool NVPTXDAGToDAGISel::tryStoreParam(SDNode *N) { break; } case NVPTXISD::StoreParamS32: { - Opcode = NVPTX::StoreParamI32; + Opcode = NVPTX::StoreParamI32_r; SDValue CvtNone = CurDAG->getTargetConstant(NVPTX::PTXCvtMode::NONE, DL, MVT::i32); SDNode *Cvt = CurDAG->getMachineNode(NVPTX::CVT_s32_s16, DL, diff --git a/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td b/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td index 393fa29ff051..c4c35a1f74ba 100644 --- a/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td +++ b/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td @@ -2637,25 +2637,46 @@ class LoadParamRegInst : [(set regclass:$dst, (LoadParam (i32 0), (i32 imm:$b)))]>; let mayStore = true in { - class StoreParamInst : - NVPTXInst<(outs), (ins regclass:$val, i32imm:$a, i32imm:$b), - !strconcat("st.param", opstr, " \t[param$a+$b], $val;"), - []>; - class StoreParamV2Inst : - NVPTXInst<(outs), (ins regclass:$val, regclass:$val2, - i32imm:$a, i32imm:$b), - !strconcat("st.param.v2", opstr, - " \t[param$a+$b], {{$val, $val2}};"), - []>; + multiclass StoreParamInst { + foreach op = [IMMType, regclass] in + if !or(support_imm, !isa(op)) then + def _ # !if(!isa(op), "r", "i") + : NVPTXInst<(outs), + (ins op:$val, i32imm:$a, i32imm:$b), + "st.param" # opstr # " \t[param$a+$b], $val;", + []>; + } - class StoreParamV4Inst : - NVPTXInst<(outs), (ins regclass:$val, regclass:$val2, regclass:$val3, - regclass:$val4, i32imm:$a, - i32imm:$b), - !strconcat("st.param.v4", opstr, - " \t[param$a+$b], {{$val, $val2, $val3, $val4}};"), - []>; + multiclass StoreParamV2Inst { + foreach op1 = [IMMType, regclass] in + foreach op2 = [IMMType, regclass] in + def _ # !if(!isa(op1), "r", "i") + # !if(!isa(op2), "r", "i") + : NVPTXInst<(outs), + (ins op1:$val1, op2:$val2, + i32imm:$a, i32imm:$b), + "st.param.v2" # opstr # " \t[param$a+$b], {{$val1, $val2}};", + []>; + } + + multiclass StoreParamV4Inst { + foreach op1 = [IMMType, regclass] in + foreach op2 = [IMMType, regclass] in + foreach op3 = [IMMType, regclass] in + foreach op4 = [IMMType, regclass] in + def _ # !if(!isa(op1), "r", "i") + # !if(!isa(op2), "r", "i") + # !if(!isa(op3), "r", "i") + # !if(!isa(op4), "r", "i") + + : NVPTXInst<(outs), + (ins op1:$val1, op2:$val2, op3:$val3, op4:$val4, + i32imm:$a, i32imm:$b), + "st.param.v4" # opstr # + " \t[param$a+$b], {{$val1, $val2, $val3, $val4}};", + []>; + } class StoreRetvalInst : NVPTXInst<(outs), (ins regclass:$val, i32imm:$a), @@ -2735,27 +2756,30 @@ def LoadParamMemV2F32 : LoadParamV2MemInst; def LoadParamMemV2F64 : LoadParamV2MemInst; def LoadParamMemV4F32 : LoadParamV4MemInst; -def StoreParamI64 : StoreParamInst; -def StoreParamI32 : StoreParamInst; - -def StoreParamI16 : StoreParamInst; -def StoreParamI8 : StoreParamInst; -def StoreParamI8TruncI32 : StoreParamInst; -def StoreParamI8TruncI64 : StoreParamInst; -def StoreParamV2I64 : StoreParamV2Inst; -def StoreParamV2I32 : StoreParamV2Inst; -def StoreParamV2I16 : StoreParamV2Inst; -def StoreParamV2I8 : StoreParamV2Inst; - -def StoreParamV4I32 : StoreParamV4Inst; -def StoreParamV4I16 : StoreParamV4Inst; -def StoreParamV4I8 : StoreParamV4Inst; - -def StoreParamF32 : StoreParamInst; -def StoreParamF64 : StoreParamInst; -def StoreParamV2F32 : StoreParamV2Inst; -def StoreParamV2F64 : StoreParamV2Inst; -def StoreParamV4F32 : StoreParamV4Inst; +defm StoreParamI64 : StoreParamInst; +defm StoreParamI32 : StoreParamInst; +defm StoreParamI16 : StoreParamInst; +defm StoreParamI8 : StoreParamInst; + +defm StoreParamI8TruncI32 : StoreParamInst; +defm StoreParamI8TruncI64 : StoreParamInst; + +defm StoreParamV2I64 : StoreParamV2Inst; +defm StoreParamV2I32 : StoreParamV2Inst; +defm StoreParamV2I16 : StoreParamV2Inst; +defm StoreParamV2I8 : StoreParamV2Inst; + +defm StoreParamV4I32 : StoreParamV4Inst; +defm StoreParamV4I16 : StoreParamV4Inst; +defm StoreParamV4I8 : StoreParamV4Inst; + +defm StoreParamF32 : StoreParamInst; +defm StoreParamF64 : StoreParamInst; + +defm StoreParamV2F32 : StoreParamV2Inst; +defm StoreParamV2F64 : StoreParamV2Inst; + +defm StoreParamV4F32 : StoreParamV4Inst; def StoreRetvalI64 : StoreRetvalInst; def StoreRetvalI32 : StoreRetvalInst; diff --git a/llvm/test/CodeGen/NVPTX/st-param-imm.ll b/llvm/test/CodeGen/NVPTX/st-param-imm.ll new file mode 100644 index 000000000000..d9e005719238 --- /dev/null +++ b/llvm/test/CodeGen/NVPTX/st-param-imm.ll @@ -0,0 +1,2002 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -march=nvptx64 | FileCheck %s +; RUN: llc < %s -march=nvptx | FileCheck %s +; RUN: %if ptxas %{ llc < %s -march=nvptx -verify-machineinstrs | %ptxas-verify %} +; RUN: %if ptxas %{ llc < %s -march=nvptx64 -verify-machineinstrs | %ptxas-verify %} + +target triple = "nvptx64-nvidia-cuda" + +%struct.A = type { i8, i16 } +%struct.char2 = type { i8, i8 } +%struct.char4 = type { i8, i8, i8, i8 } +%struct.short2 = type { i16, i16 } +%struct.short4 = type { i16, i16, i16, i16 } +%struct.int2 = type { i32, i32 } +%struct.int4 = type { i32, i32, i32, i32 } +%struct.longlong2 = type { i64, i64 } +%struct.float2 = type { float, float } +%struct.float4 = type { float, float, float, float } +%struct.double2 = type { double, double } + +define void @st_param_i8_i16() { +; CHECK-LABEL: st_param_i8_i16( +; CHECK: { +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: { // callseq 0, 0 +; CHECK-NEXT: .param .align 2 .b8 param0[4]; +; CHECK-NEXT: st.param.b8 [param0+0], 1; +; CHECK-NEXT: st.param.b16 [param0+2], 2; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_i8_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 0 +; CHECK-NEXT: ret; + call void @call_i8_i16(%struct.A { i8 1, i16 2 }) + ret void +} + +define void @st_param_i32() { +; CHECK-LABEL: st_param_i32( +; CHECK: { +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: { // callseq 1, 0 +; CHECK-NEXT: .param .b32 param0; +; CHECK-NEXT: st.param.b32 [param0+0], 3; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 1 +; CHECK-NEXT: ret; + call void @call_i32(i32 3) + ret void +} + +define void @st_param_i64() { +; CHECK-LABEL: st_param_i64( +; CHECK: { +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: { // callseq 2, 0 +; CHECK-NEXT: .param .b64 param0; +; CHECK-NEXT: st.param.b64 [param0+0], 4; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_i64, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 2 +; CHECK-NEXT: ret; + call void @call_i64(i64 4) + ret void +} + +define void @st_param_f32() { +; CHECK-LABEL: st_param_f32( +; CHECK: { +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: { // callseq 3, 0 +; CHECK-NEXT: .param .b32 param0; +; CHECK-NEXT: st.param.f32 [param0+0], 0f40A00000; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 3 +; CHECK-NEXT: ret; + call void @call_f32(float 5.0) + ret void +} + +define void @st_param_f64() { +; CHECK-LABEL: st_param_f64( +; CHECK: { +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: { // callseq 4, 0 +; CHECK-NEXT: .param .b64 param0; +; CHECK-NEXT: st.param.f64 [param0+0], 0d4018000000000000; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_f64, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 4 +; CHECK-NEXT: ret; + call void @call_f64(double 6.0) + ret void +} + +declare void @call_i8_i16(%struct.A) +declare void @call_i32(i32) +declare void @call_i64(i64) +declare void @call_f32(float) +declare void @call_f64(double) + +define void @st_param_v2_i8_ii() { +; CHECK-LABEL: st_param_v2_i8_ii( +; CHECK: { +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: { // callseq 5, 0 +; CHECK-NEXT: .param .align 2 .b8 param0[2]; +; CHECK-NEXT: st.param.v2.b8 [param0+0], {1, 2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 5 +; CHECK-NEXT: ret; + call void @call_v2_i8(%struct.char2 { i8 1, i8 2 }) + ret void +} +define void @st_param_v2_i8_ir(i8 %val) { +; CHECK-LABEL: st_param_v2_i8_ir( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u8 %rs1, [st_param_v2_i8_ir_param_0]; +; CHECK-NEXT: { // callseq 6, 0 +; CHECK-NEXT: .param .align 2 .b8 param0[2]; +; CHECK-NEXT: st.param.v2.b8 [param0+0], {1, %rs1}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 6 +; CHECK-NEXT: ret; + %struct.ir0 = insertvalue %struct.char2 poison, i8 1, 0 + %struct.ir1 = insertvalue %struct.char2 %struct.ir0, i8 %val, 1 + call void @call_v2_i8(%struct.char2 %struct.ir1) + ret void +} +define void @st_param_v2_i8_ri(i8 %val) { +; CHECK-LABEL: st_param_v2_i8_ri( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u8 %rs1, [st_param_v2_i8_ri_param_0]; +; CHECK-NEXT: { // callseq 7, 0 +; CHECK-NEXT: .param .align 2 .b8 param0[2]; +; CHECK-NEXT: st.param.v2.b8 [param0+0], {%rs1, 2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 7 +; CHECK-NEXT: ret; + %struct.ri0 = insertvalue %struct.char2 poison, i8 %val, 0 + %struct.ri1 = insertvalue %struct.char2 %struct.ri0, i8 2, 1 + call void @call_v2_i8(%struct.char2 %struct.ri1) + ret void +} + +define void @st_param_v2_i16_ii() { +; CHECK-LABEL: st_param_v2_i16_ii( +; CHECK: { +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: { // callseq 8, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v2.b16 [param0+0], {1, 2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 8 +; CHECK-NEXT: ret; + call void @call_v2_i16(%struct.short2 { i16 1, i16 2 }) + ret void +} +define void @st_param_v2_i16_ir(i16 %val) { +; CHECK-LABEL: st_param_v2_i16_ir( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [st_param_v2_i16_ir_param_0]; +; CHECK-NEXT: { // callseq 9, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v2.b16 [param0+0], {1, %rs1}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 9 +; CHECK-NEXT: ret; + %struct.ir0 = insertvalue %struct.short2 poison, i16 1, 0 + %struct.ir1 = insertvalue %struct.short2 %struct.ir0, i16 %val, 1 + call void @call_v2_i16(%struct.short2 %struct.ir1) + ret void +} +define void @st_param_v2_i16_ri(i16 %val) { +; CHECK-LABEL: st_param_v2_i16_ri( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [st_param_v2_i16_ri_param_0]; +; CHECK-NEXT: { // callseq 10, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v2.b16 [param0+0], {%rs1, 2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 10 +; CHECK-NEXT: ret; + %struct.ri0 = insertvalue %struct.short2 poison, i16 %val, 0 + %struct.ri1 = insertvalue %struct.short2 %struct.ri0, i16 2, 1 + call void @call_v2_i16(%struct.short2 %struct.ri1) + ret void +} + +define void @st_param_v2_i32_ii() { +; CHECK-LABEL: st_param_v2_i32_ii( +; CHECK: { +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: { // callseq 11, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v2.b32 [param0+0], {1, 2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 11 +; CHECK-NEXT: ret; + call void @call_v2_i32(%struct.int2 { i32 1, i32 2 }) + ret void +} +define void @st_param_v2_i32_ir(i32 %val) { +; CHECK-LABEL: st_param_v2_i32_ir( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [st_param_v2_i32_ir_param_0]; +; CHECK-NEXT: { // callseq 12, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v2.b32 [param0+0], {1, %r1}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 12 +; CHECK-NEXT: ret; + %struct.ir0 = insertvalue %struct.int2 poison, i32 1, 0 + %struct.ir1 = insertvalue %struct.int2 %struct.ir0, i32 %val, 1 + call void @call_v2_i32(%struct.int2 %struct.ir1) + ret void +} +define void @st_param_v2_i32_ri(i32 %val) { +; CHECK-LABEL: st_param_v2_i32_ri( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [st_param_v2_i32_ri_param_0]; +; CHECK-NEXT: { // callseq 13, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v2.b32 [param0+0], {%r1, 2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 13 +; CHECK-NEXT: ret; + %struct.ri0 = insertvalue %struct.int2 poison, i32 %val, 0 + %struct.ri1 = insertvalue %struct.int2 %struct.ri0, i32 2, 1 + call void @call_v2_i32(%struct.int2 %struct.ri1) + ret void +} + +define void @st_param_v2_i64_ii() { +; CHECK-LABEL: st_param_v2_i64_ii( +; CHECK: { +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: { // callseq 14, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v2.b64 [param0+0], {1, 2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_i64, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 14 +; CHECK-NEXT: ret; + call void @call_v2_i64(%struct.longlong2 { i64 1, i64 2 }) + ret void +} +define void @st_param_v2_i64_ir(i64 %val) { +; CHECK-LABEL: st_param_v2_i64_ir( +; CHECK: { +; CHECK-NEXT: .reg .b64 %rd<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u64 %rd1, [st_param_v2_i64_ir_param_0]; +; CHECK-NEXT: { // callseq 15, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v2.b64 [param0+0], {1, %rd1}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_i64, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 15 +; CHECK-NEXT: ret; + %struct.ir0 = insertvalue %struct.longlong2 poison, i64 1, 0 + %struct.ir1 = insertvalue %struct.longlong2 %struct.ir0, i64 %val, 1 + call void @call_v2_i64(%struct.longlong2 %struct.ir1) + ret void +} +define void @st_param_v2_i64_ri(i64 %val) { +; CHECK-LABEL: st_param_v2_i64_ri( +; CHECK: { +; CHECK-NEXT: .reg .b64 %rd<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u64 %rd1, [st_param_v2_i64_ri_param_0]; +; CHECK-NEXT: { // callseq 16, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v2.b64 [param0+0], {%rd1, 2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_i64, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 16 +; CHECK-NEXT: ret; + %struct.ri0 = insertvalue %struct.longlong2 poison, i64 %val, 0 + %struct.ri1 = insertvalue %struct.longlong2 %struct.ri0, i64 2, 1 + call void @call_v2_i64(%struct.longlong2 %struct.ri1) + ret void +} + +define void @st_param_v2_f32_ii(float %val) { +; CHECK-LABEL: st_param_v2_f32_ii( +; CHECK: { +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: { // callseq 17, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v2.f32 [param0+0], {0f3F800000, 0f40000000}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 17 +; CHECK-NEXT: ret; + call void @call_v2_f32(%struct.float2 { float 1.0, float 2.0 }) + ret void +} +define void @st_param_v2_f32_ir(float %val) { +; CHECK-LABEL: st_param_v2_f32_ir( +; CHECK: { +; CHECK-NEXT: .reg .f32 %f<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f32 %f1, [st_param_v2_f32_ir_param_0]; +; CHECK-NEXT: { // callseq 18, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v2.f32 [param0+0], {0f3F800000, %f1}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 18 +; CHECK-NEXT: ret; + %struct.ir0 = insertvalue %struct.float2 poison, float 1.0, 0 + %struct.ir1 = insertvalue %struct.float2 %struct.ir0, float %val, 1 + call void @call_v2_f32(%struct.float2 %struct.ir1) + ret void +} +define void @st_param_v2_f32_ri(float %val) { +; CHECK-LABEL: st_param_v2_f32_ri( +; CHECK: { +; CHECK-NEXT: .reg .f32 %f<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f32 %f1, [st_param_v2_f32_ri_param_0]; +; CHECK-NEXT: { // callseq 19, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v2.f32 [param0+0], {%f1, 0f40000000}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 19 +; CHECK-NEXT: ret; + %struct.ri0 = insertvalue %struct.float2 poison, float %val, 0 + %struct.ri1 = insertvalue %struct.float2 %struct.ri0, float 2.0, 1 + call void @call_v2_f32(%struct.float2 %struct.ri1) + ret void +} + +define void @st_param_v2_f64_ii(double %val) { +; CHECK-LABEL: st_param_v2_f64_ii( +; CHECK: { +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: { // callseq 20, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v2.f64 [param0+0], {0d3FF0000000000000, 0d4000000000000000}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_f64, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 20 +; CHECK-NEXT: ret; + call void @call_v2_f64(%struct.double2 { double 1.0, double 2.0 }) + ret void +} +define void @st_param_v2_f64_ir(double %val) { +; CHECK-LABEL: st_param_v2_f64_ir( +; CHECK: { +; CHECK-NEXT: .reg .f64 %fd<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f64 %fd1, [st_param_v2_f64_ir_param_0]; +; CHECK-NEXT: { // callseq 21, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v2.f64 [param0+0], {0d3FF0000000000000, %fd1}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_f64, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 21 +; CHECK-NEXT: ret; + %struct.ir0 = insertvalue %struct.double2 poison, double 1.0, 0 + %struct.ir1 = insertvalue %struct.double2 %struct.ir0, double %val, 1 + call void @call_v2_f64(%struct.double2 %struct.ir1) + ret void +} +define void @st_param_v2_f64_ri(double %val) { +; CHECK-LABEL: st_param_v2_f64_ri( +; CHECK: { +; CHECK-NEXT: .reg .f64 %fd<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f64 %fd1, [st_param_v2_f64_ri_param_0]; +; CHECK-NEXT: { // callseq 22, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v2.f64 [param0+0], {%fd1, 0d4000000000000000}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v2_f64, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 22 +; CHECK-NEXT: ret; + %struct.ri0 = insertvalue %struct.double2 poison, double %val, 0 + %struct.ri1 = insertvalue %struct.double2 %struct.ri0, double 2.0, 1 + call void @call_v2_f64(%struct.double2 %struct.ri1) + ret void +} + +declare void @call_v2_i8(%struct.char2 alignstack(2)) +declare void @call_v2_i16(%struct.short2 alignstack(4)) +declare void @call_v2_i32(%struct.int2 alignstack(8)) +declare void @call_v2_i64(%struct.longlong2 alignstack(16)) +declare void @call_v2_f32(%struct.float2 alignstack(8)) +declare void @call_v2_f64(%struct.double2 alignstack(16)) + +define void @st_param_v4_i8_iiii() { +; CHECK-LABEL: st_param_v4_i8_iiii( +; CHECK: { +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: { // callseq 23, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v4.b8 [param0+0], {1, 2, 3, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 23 +; CHECK-NEXT: ret; + call void @call_v4_i8(%struct.char4 { i8 1, i8 2, i8 3, i8 4 }) + ret void +} +define void @st_param_v4_i8_irrr(i8 %b, i8 %c, i8 %d) { +; CHECK-LABEL: st_param_v4_i8_irrr( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u8 %rs1, [st_param_v4_i8_irrr_param_0]; +; CHECK-NEXT: ld.param.u8 %rs2, [st_param_v4_i8_irrr_param_1]; +; CHECK-NEXT: ld.param.u8 %rs3, [st_param_v4_i8_irrr_param_2]; +; CHECK-NEXT: { // callseq 24, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v4.b8 [param0+0], {1, %rs1, %rs2, %rs3}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 24 +; CHECK-NEXT: ret; + %struct.irrr0 = insertvalue %struct.char4 poison, i8 1, 0 + %struct.irrr1 = insertvalue %struct.char4 %struct.irrr0, i8 %b, 1 + %struct.irrr2 = insertvalue %struct.char4 %struct.irrr1, i8 %c, 2 + %struct.irrr3 = insertvalue %struct.char4 %struct.irrr2, i8 %d, 3 + call void @call_v4_i8(%struct.char4 %struct.irrr3) + ret void +} +define void @st_param_v4_i8_rirr(i8 %a, i8 %c, i8 %d) { +; CHECK-LABEL: st_param_v4_i8_rirr( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u8 %rs1, [st_param_v4_i8_rirr_param_0]; +; CHECK-NEXT: ld.param.u8 %rs2, [st_param_v4_i8_rirr_param_1]; +; CHECK-NEXT: ld.param.u8 %rs3, [st_param_v4_i8_rirr_param_2]; +; CHECK-NEXT: { // callseq 25, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v4.b8 [param0+0], {%rs1, 2, %rs2, %rs3}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 25 +; CHECK-NEXT: ret; + %struct.rirr0 = insertvalue %struct.char4 poison, i8 %a, 0 + %struct.rirr1 = insertvalue %struct.char4 %struct.rirr0, i8 2, 1 + %struct.rirr2 = insertvalue %struct.char4 %struct.rirr1, i8 %c, 2 + %struct.rirr3 = insertvalue %struct.char4 %struct.rirr2, i8 %d, 3 + call void @call_v4_i8(%struct.char4 %struct.rirr3) + ret void +} +define void @st_param_v4_i8_rrir(i8 %a, i8 %b, i8 %d) { +; CHECK-LABEL: st_param_v4_i8_rrir( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u8 %rs1, [st_param_v4_i8_rrir_param_0]; +; CHECK-NEXT: ld.param.u8 %rs2, [st_param_v4_i8_rrir_param_1]; +; CHECK-NEXT: ld.param.u8 %rs3, [st_param_v4_i8_rrir_param_2]; +; CHECK-NEXT: { // callseq 26, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v4.b8 [param0+0], {%rs1, %rs2, 3, %rs3}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 26 +; CHECK-NEXT: ret; + %struct.rrir0 = insertvalue %struct.char4 poison, i8 %a, 0 + %struct.rrir1 = insertvalue %struct.char4 %struct.rrir0, i8 %b, 1 + %struct.rrir2 = insertvalue %struct.char4 %struct.rrir1, i8 3, 2 + %struct.rrir3 = insertvalue %struct.char4 %struct.rrir2, i8 %d, 3 + call void @call_v4_i8(%struct.char4 %struct.rrir3) + ret void +} +define void @st_param_v4_i8_rrri(i8 %a, i8 %b, i8 %c) { +; CHECK-LABEL: st_param_v4_i8_rrri( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u8 %rs1, [st_param_v4_i8_rrri_param_0]; +; CHECK-NEXT: ld.param.u8 %rs2, [st_param_v4_i8_rrri_param_1]; +; CHECK-NEXT: ld.param.u8 %rs3, [st_param_v4_i8_rrri_param_2]; +; CHECK-NEXT: { // callseq 27, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v4.b8 [param0+0], {%rs1, %rs2, %rs3, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 27 +; CHECK-NEXT: ret; + %struct.rrri0 = insertvalue %struct.char4 poison, i8 %a, 0 + %struct.rrri1 = insertvalue %struct.char4 %struct.rrri0, i8 %b, 1 + %struct.rrri2 = insertvalue %struct.char4 %struct.rrri1, i8 %c, 2 + %struct.rrri3 = insertvalue %struct.char4 %struct.rrri2, i8 4, 3 + call void @call_v4_i8(%struct.char4 %struct.rrri3) + ret void +} +define void @st_param_v4_i8_iirr(i8 %c, i8 %d) { +; CHECK-LABEL: st_param_v4_i8_iirr( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u8 %rs1, [st_param_v4_i8_iirr_param_0]; +; CHECK-NEXT: ld.param.u8 %rs2, [st_param_v4_i8_iirr_param_1]; +; CHECK-NEXT: { // callseq 28, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v4.b8 [param0+0], {1, 2, %rs1, %rs2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 28 +; CHECK-NEXT: ret; + %struct.iirr0 = insertvalue %struct.char4 poison, i8 1, 0 + %struct.iirr1 = insertvalue %struct.char4 %struct.iirr0, i8 2, 1 + %struct.iirr2 = insertvalue %struct.char4 %struct.iirr1, i8 %c, 2 + %struct.iirr3 = insertvalue %struct.char4 %struct.iirr2, i8 %d, 3 + call void @call_v4_i8(%struct.char4 %struct.iirr3) + ret void +} +define void @st_param_v4_i8_irir(i8 %b, i8 %d) { +; CHECK-LABEL: st_param_v4_i8_irir( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u8 %rs1, [st_param_v4_i8_irir_param_0]; +; CHECK-NEXT: ld.param.u8 %rs2, [st_param_v4_i8_irir_param_1]; +; CHECK-NEXT: { // callseq 29, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v4.b8 [param0+0], {1, %rs1, 3, %rs2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 29 +; CHECK-NEXT: ret; + %struct.irir0 = insertvalue %struct.char4 poison, i8 1, 0 + %struct.irir1 = insertvalue %struct.char4 %struct.irir0, i8 %b, 1 + %struct.irir2 = insertvalue %struct.char4 %struct.irir1, i8 3, 2 + %struct.irir3 = insertvalue %struct.char4 %struct.irir2, i8 %d, 3 + call void @call_v4_i8(%struct.char4 %struct.irir3) + ret void +} +define void @st_param_v4_i8_irri(i8 %b, i8 %c) { +; CHECK-LABEL: st_param_v4_i8_irri( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u8 %rs1, [st_param_v4_i8_irri_param_0]; +; CHECK-NEXT: ld.param.u8 %rs2, [st_param_v4_i8_irri_param_1]; +; CHECK-NEXT: { // callseq 30, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v4.b8 [param0+0], {1, %rs1, %rs2, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 30 +; CHECK-NEXT: ret; + %struct.irri0 = insertvalue %struct.char4 poison, i8 1, 0 + %struct.irri1 = insertvalue %struct.char4 %struct.irri0, i8 %b, 1 + %struct.irri2 = insertvalue %struct.char4 %struct.irri1, i8 %c, 2 + %struct.irri3 = insertvalue %struct.char4 %struct.irri2, i8 4, 3 + call void @call_v4_i8(%struct.char4 %struct.irri3) + ret void +} +define void @st_param_v4_i8_riir(i8 %a, i8 %d) { +; CHECK-LABEL: st_param_v4_i8_riir( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u8 %rs1, [st_param_v4_i8_riir_param_0]; +; CHECK-NEXT: ld.param.u8 %rs2, [st_param_v4_i8_riir_param_1]; +; CHECK-NEXT: { // callseq 31, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v4.b8 [param0+0], {%rs1, 2, 3, %rs2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 31 +; CHECK-NEXT: ret; + %struct.riir0 = insertvalue %struct.char4 poison, i8 %a, 0 + %struct.riir1 = insertvalue %struct.char4 %struct.riir0, i8 2, 1 + %struct.riir2 = insertvalue %struct.char4 %struct.riir1, i8 3, 2 + %struct.riir3 = insertvalue %struct.char4 %struct.riir2, i8 %d, 3 + call void @call_v4_i8(%struct.char4 %struct.riir3) + ret void +} +define void @st_param_v4_i8_riri(i8 %a, i8 %c) { +; CHECK-LABEL: st_param_v4_i8_riri( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u8 %rs1, [st_param_v4_i8_riri_param_0]; +; CHECK-NEXT: ld.param.u8 %rs2, [st_param_v4_i8_riri_param_1]; +; CHECK-NEXT: { // callseq 32, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v4.b8 [param0+0], {%rs1, 2, %rs2, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 32 +; CHECK-NEXT: ret; + %struct.riri0 = insertvalue %struct.char4 poison, i8 %a, 0 + %struct.riri1 = insertvalue %struct.char4 %struct.riri0, i8 2, 1 + %struct.riri2 = insertvalue %struct.char4 %struct.riri1, i8 %c, 2 + %struct.riri3 = insertvalue %struct.char4 %struct.riri2, i8 4, 3 + call void @call_v4_i8(%struct.char4 %struct.riri3) + ret void +} +define void @st_param_v4_i8_rrii(i8 %a, i8 %b) { +; CHECK-LABEL: st_param_v4_i8_rrii( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u8 %rs1, [st_param_v4_i8_rrii_param_0]; +; CHECK-NEXT: ld.param.u8 %rs2, [st_param_v4_i8_rrii_param_1]; +; CHECK-NEXT: { // callseq 33, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v4.b8 [param0+0], {%rs1, %rs2, 3, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 33 +; CHECK-NEXT: ret; + %struct.rrii0 = insertvalue %struct.char4 poison, i8 %a, 0 + %struct.rrii1 = insertvalue %struct.char4 %struct.rrii0, i8 %b, 1 + %struct.rrii2 = insertvalue %struct.char4 %struct.rrii1, i8 3, 2 + %struct.rrii3 = insertvalue %struct.char4 %struct.rrii2, i8 4, 3 + call void @call_v4_i8(%struct.char4 %struct.rrii3) + ret void +} +define void @st_param_v4_i8_iiir(i8 %d) { +; CHECK-LABEL: st_param_v4_i8_iiir( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u8 %rs1, [st_param_v4_i8_iiir_param_0]; +; CHECK-NEXT: { // callseq 34, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v4.b8 [param0+0], {1, 2, 3, %rs1}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 34 +; CHECK-NEXT: ret; + %struct.iiir0 = insertvalue %struct.char4 poison, i8 1, 0 + %struct.iiir1 = insertvalue %struct.char4 %struct.iiir0, i8 2, 1 + %struct.iiir2 = insertvalue %struct.char4 %struct.iiir1, i8 3, 2 + %struct.iiir3 = insertvalue %struct.char4 %struct.iiir2, i8 %d, 3 + call void @call_v4_i8(%struct.char4 %struct.iiir3) + ret void +} +define void @st_param_v4_i8_iiri(i8 %c) { +; CHECK-LABEL: st_param_v4_i8_iiri( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u8 %rs1, [st_param_v4_i8_iiri_param_0]; +; CHECK-NEXT: { // callseq 35, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v4.b8 [param0+0], {1, 2, %rs1, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 35 +; CHECK-NEXT: ret; + %struct.iiri0 = insertvalue %struct.char4 poison, i8 1, 0 + %struct.iiri1 = insertvalue %struct.char4 %struct.iiri0, i8 2, 1 + %struct.iiri2 = insertvalue %struct.char4 %struct.iiri1, i8 %c, 2 + %struct.iiri3 = insertvalue %struct.char4 %struct.iiri2, i8 4, 3 + call void @call_v4_i8(%struct.char4 %struct.iiri3) + ret void +} +define void @st_param_v4_i8_irii(i8 %b) { +; CHECK-LABEL: st_param_v4_i8_irii( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u8 %rs1, [st_param_v4_i8_irii_param_0]; +; CHECK-NEXT: { // callseq 36, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v4.b8 [param0+0], {1, %rs1, 3, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 36 +; CHECK-NEXT: ret; + %struct.irii0 = insertvalue %struct.char4 poison, i8 1, 0 + %struct.irii1 = insertvalue %struct.char4 %struct.irii0, i8 %b, 1 + %struct.irii2 = insertvalue %struct.char4 %struct.irii1, i8 3, 2 + %struct.irii3 = insertvalue %struct.char4 %struct.irii2, i8 4, 3 + call void @call_v4_i8(%struct.char4 %struct.irii3) + ret void +} +define void @st_param_v4_i8_riii(i8 %a) { +; CHECK-LABEL: st_param_v4_i8_riii( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u8 %rs1, [st_param_v4_i8_riii_param_0]; +; CHECK-NEXT: { // callseq 37, 0 +; CHECK-NEXT: .param .align 4 .b8 param0[4]; +; CHECK-NEXT: st.param.v4.b8 [param0+0], {%rs1, 2, 3, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i8, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 37 +; CHECK-NEXT: ret; + %struct.riii0 = insertvalue %struct.char4 poison, i8 %a, 0 + %struct.riii1 = insertvalue %struct.char4 %struct.riii0, i8 2, 1 + %struct.riii2 = insertvalue %struct.char4 %struct.riii1, i8 3, 2 + %struct.riii3 = insertvalue %struct.char4 %struct.riii2, i8 4, 3 + call void @call_v4_i8(%struct.char4 %struct.riii3) + ret void +} + +define void @st_param_v4_i16_iiii() { +; CHECK-LABEL: st_param_v4_i16_iiii( +; CHECK: { +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: { // callseq 38, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v4.b16 [param0+0], {1, 2, 3, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 38 +; CHECK-NEXT: ret; + call void @call_v4_i16(%struct.short4 { i16 1, i16 2, i16 3, i16 4 }) + ret void +} +define void @st_param_v4_i16_irrr(i16 %b, i16 %c, i16 %d) { +; CHECK-LABEL: st_param_v4_i16_irrr( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [st_param_v4_i16_irrr_param_0]; +; CHECK-NEXT: ld.param.u16 %rs2, [st_param_v4_i16_irrr_param_1]; +; CHECK-NEXT: ld.param.u16 %rs3, [st_param_v4_i16_irrr_param_2]; +; CHECK-NEXT: { // callseq 39, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v4.b16 [param0+0], {1, %rs1, %rs2, %rs3}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 39 +; CHECK-NEXT: ret; + %struct.irrr0 = insertvalue %struct.short4 poison, i16 1, 0 + %struct.irrr1 = insertvalue %struct.short4 %struct.irrr0, i16 %b, 1 + %struct.irrr2 = insertvalue %struct.short4 %struct.irrr1, i16 %c, 2 + %struct.irrr3 = insertvalue %struct.short4 %struct.irrr2, i16 %d, 3 + call void @call_v4_i16(%struct.short4 %struct.irrr3) + ret void +} +define void @st_param_v4_i16_rirr(i16 %a, i16 %c, i16 %d) { +; CHECK-LABEL: st_param_v4_i16_rirr( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [st_param_v4_i16_rirr_param_0]; +; CHECK-NEXT: ld.param.u16 %rs2, [st_param_v4_i16_rirr_param_1]; +; CHECK-NEXT: ld.param.u16 %rs3, [st_param_v4_i16_rirr_param_2]; +; CHECK-NEXT: { // callseq 40, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v4.b16 [param0+0], {%rs1, 2, %rs2, %rs3}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 40 +; CHECK-NEXT: ret; + %struct.rirr0 = insertvalue %struct.short4 poison, i16 %a, 0 + %struct.rirr1 = insertvalue %struct.short4 %struct.rirr0, i16 2, 1 + %struct.rirr2 = insertvalue %struct.short4 %struct.rirr1, i16 %c, 2 + %struct.rirr3 = insertvalue %struct.short4 %struct.rirr2, i16 %d, 3 + call void @call_v4_i16(%struct.short4 %struct.rirr3) + ret void +} +define void @st_param_v4_i16_rrir(i16 %a, i16 %b, i16 %d) { +; CHECK-LABEL: st_param_v4_i16_rrir( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [st_param_v4_i16_rrir_param_0]; +; CHECK-NEXT: ld.param.u16 %rs2, [st_param_v4_i16_rrir_param_1]; +; CHECK-NEXT: ld.param.u16 %rs3, [st_param_v4_i16_rrir_param_2]; +; CHECK-NEXT: { // callseq 41, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v4.b16 [param0+0], {%rs1, %rs2, 3, %rs3}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 41 +; CHECK-NEXT: ret; + %struct.rrir0 = insertvalue %struct.short4 poison, i16 %a, 0 + %struct.rrir1 = insertvalue %struct.short4 %struct.rrir0, i16 %b, 1 + %struct.rrir2 = insertvalue %struct.short4 %struct.rrir1, i16 3, 2 + %struct.rrir3 = insertvalue %struct.short4 %struct.rrir2, i16 %d, 3 + call void @call_v4_i16(%struct.short4 %struct.rrir3) + ret void +} +define void @st_param_v4_i16_rrri(i16 %a, i16 %b, i16 %c) { +; CHECK-LABEL: st_param_v4_i16_rrri( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [st_param_v4_i16_rrri_param_0]; +; CHECK-NEXT: ld.param.u16 %rs2, [st_param_v4_i16_rrri_param_1]; +; CHECK-NEXT: ld.param.u16 %rs3, [st_param_v4_i16_rrri_param_2]; +; CHECK-NEXT: { // callseq 42, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v4.b16 [param0+0], {%rs1, %rs2, %rs3, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 42 +; CHECK-NEXT: ret; + %struct.rrri0 = insertvalue %struct.short4 poison, i16 %a, 0 + %struct.rrri1 = insertvalue %struct.short4 %struct.rrri0, i16 %b, 1 + %struct.rrri2 = insertvalue %struct.short4 %struct.rrri1, i16 %c, 2 + %struct.rrri3 = insertvalue %struct.short4 %struct.rrri2, i16 4, 3 + call void @call_v4_i16(%struct.short4 %struct.rrri3) + ret void +} +define void @st_param_v4_i16_iirr(i16 %c, i16 %d) { +; CHECK-LABEL: st_param_v4_i16_iirr( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [st_param_v4_i16_iirr_param_0]; +; CHECK-NEXT: ld.param.u16 %rs2, [st_param_v4_i16_iirr_param_1]; +; CHECK-NEXT: { // callseq 43, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v4.b16 [param0+0], {1, 2, %rs1, %rs2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 43 +; CHECK-NEXT: ret; + %struct.iirr0 = insertvalue %struct.short4 poison, i16 1, 0 + %struct.iirr1 = insertvalue %struct.short4 %struct.iirr0, i16 2, 1 + %struct.iirr2 = insertvalue %struct.short4 %struct.iirr1, i16 %c, 2 + %struct.iirr3 = insertvalue %struct.short4 %struct.iirr2, i16 %d, 3 + call void @call_v4_i16(%struct.short4 %struct.iirr3) + ret void +} +define void @st_param_v4_i16_irir(i16 %b, i16 %d) { +; CHECK-LABEL: st_param_v4_i16_irir( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [st_param_v4_i16_irir_param_0]; +; CHECK-NEXT: ld.param.u16 %rs2, [st_param_v4_i16_irir_param_1]; +; CHECK-NEXT: { // callseq 44, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v4.b16 [param0+0], {1, %rs1, 3, %rs2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 44 +; CHECK-NEXT: ret; + %struct.irir0 = insertvalue %struct.short4 poison, i16 1, 0 + %struct.irir1 = insertvalue %struct.short4 %struct.irir0, i16 %b, 1 + %struct.irir2 = insertvalue %struct.short4 %struct.irir1, i16 3, 2 + %struct.irir3 = insertvalue %struct.short4 %struct.irir2, i16 %d, 3 + call void @call_v4_i16(%struct.short4 %struct.irir3) + ret void +} +define void @st_param_v4_i16_irri(i16 %b, i16 %c) { +; CHECK-LABEL: st_param_v4_i16_irri( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [st_param_v4_i16_irri_param_0]; +; CHECK-NEXT: ld.param.u16 %rs2, [st_param_v4_i16_irri_param_1]; +; CHECK-NEXT: { // callseq 45, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v4.b16 [param0+0], {1, %rs1, %rs2, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 45 +; CHECK-NEXT: ret; + %struct.irri0 = insertvalue %struct.short4 poison, i16 1, 0 + %struct.irri1 = insertvalue %struct.short4 %struct.irri0, i16 %b, 1 + %struct.irri2 = insertvalue %struct.short4 %struct.irri1, i16 %c, 2 + %struct.irri3 = insertvalue %struct.short4 %struct.irri2, i16 4, 3 + call void @call_v4_i16(%struct.short4 %struct.irri3) + ret void +} +define void @st_param_v4_i16_riir(i16 %a, i16 %d) { +; CHECK-LABEL: st_param_v4_i16_riir( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [st_param_v4_i16_riir_param_0]; +; CHECK-NEXT: ld.param.u16 %rs2, [st_param_v4_i16_riir_param_1]; +; CHECK-NEXT: { // callseq 46, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v4.b16 [param0+0], {%rs1, 2, 3, %rs2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 46 +; CHECK-NEXT: ret; + %struct.riir0 = insertvalue %struct.short4 poison, i16 %a, 0 + %struct.riir1 = insertvalue %struct.short4 %struct.riir0, i16 2, 1 + %struct.riir2 = insertvalue %struct.short4 %struct.riir1, i16 3, 2 + %struct.riir3 = insertvalue %struct.short4 %struct.riir2, i16 %d, 3 + call void @call_v4_i16(%struct.short4 %struct.riir3) + ret void +} +define void @st_param_v4_i16_riri(i16 %a, i16 %c) { +; CHECK-LABEL: st_param_v4_i16_riri( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [st_param_v4_i16_riri_param_0]; +; CHECK-NEXT: ld.param.u16 %rs2, [st_param_v4_i16_riri_param_1]; +; CHECK-NEXT: { // callseq 47, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v4.b16 [param0+0], {%rs1, 2, %rs2, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 47 +; CHECK-NEXT: ret; + %struct.riri0 = insertvalue %struct.short4 poison, i16 %a, 0 + %struct.riri1 = insertvalue %struct.short4 %struct.riri0, i16 2, 1 + %struct.riri2 = insertvalue %struct.short4 %struct.riri1, i16 %c, 2 + %struct.riri3 = insertvalue %struct.short4 %struct.riri2, i16 4, 3 + call void @call_v4_i16(%struct.short4 %struct.riri3) + ret void +} +define void @st_param_v4_i16_rrii(i16 %a, i16 %b) { +; CHECK-LABEL: st_param_v4_i16_rrii( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [st_param_v4_i16_rrii_param_0]; +; CHECK-NEXT: ld.param.u16 %rs2, [st_param_v4_i16_rrii_param_1]; +; CHECK-NEXT: { // callseq 48, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v4.b16 [param0+0], {%rs1, %rs2, 3, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 48 +; CHECK-NEXT: ret; + %struct.rrii0 = insertvalue %struct.short4 poison, i16 %a, 0 + %struct.rrii1 = insertvalue %struct.short4 %struct.rrii0, i16 %b, 1 + %struct.rrii2 = insertvalue %struct.short4 %struct.rrii1, i16 3, 2 + %struct.rrii3 = insertvalue %struct.short4 %struct.rrii2, i16 4, 3 + call void @call_v4_i16(%struct.short4 %struct.rrii3) + ret void +} +define void @st_param_v4_i16_iiir(i16 %d) { +; CHECK-LABEL: st_param_v4_i16_iiir( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [st_param_v4_i16_iiir_param_0]; +; CHECK-NEXT: { // callseq 49, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v4.b16 [param0+0], {1, 2, 3, %rs1}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 49 +; CHECK-NEXT: ret; + %struct.iiir0 = insertvalue %struct.short4 poison, i16 1, 0 + %struct.iiir1 = insertvalue %struct.short4 %struct.iiir0, i16 2, 1 + %struct.iiir2 = insertvalue %struct.short4 %struct.iiir1, i16 3, 2 + %struct.iiir3 = insertvalue %struct.short4 %struct.iiir2, i16 %d, 3 + call void @call_v4_i16(%struct.short4 %struct.iiir3) + ret void +} +define void @st_param_v4_i16_iiri(i16 %c) { +; CHECK-LABEL: st_param_v4_i16_iiri( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [st_param_v4_i16_iiri_param_0]; +; CHECK-NEXT: { // callseq 50, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v4.b16 [param0+0], {1, 2, %rs1, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 50 +; CHECK-NEXT: ret; + %struct.iiri0 = insertvalue %struct.short4 poison, i16 1, 0 + %struct.iiri1 = insertvalue %struct.short4 %struct.iiri0, i16 2, 1 + %struct.iiri2 = insertvalue %struct.short4 %struct.iiri1, i16 %c, 2 + %struct.iiri3 = insertvalue %struct.short4 %struct.iiri2, i16 4, 3 + call void @call_v4_i16(%struct.short4 %struct.iiri3) + ret void +} +define void @st_param_v4_i16_irii(i16 %b) { +; CHECK-LABEL: st_param_v4_i16_irii( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [st_param_v4_i16_irii_param_0]; +; CHECK-NEXT: { // callseq 51, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v4.b16 [param0+0], {1, %rs1, 3, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 51 +; CHECK-NEXT: ret; + %struct.irii0 = insertvalue %struct.short4 poison, i16 1, 0 + %struct.irii1 = insertvalue %struct.short4 %struct.irii0, i16 %b, 1 + %struct.irii2 = insertvalue %struct.short4 %struct.irii1, i16 3, 2 + %struct.irii3 = insertvalue %struct.short4 %struct.irii2, i16 4, 3 + call void @call_v4_i16(%struct.short4 %struct.irii3) + ret void +} +define void @st_param_v4_i16_riii(i16 %a) { +; CHECK-LABEL: st_param_v4_i16_riii( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [st_param_v4_i16_riii_param_0]; +; CHECK-NEXT: { // callseq 52, 0 +; CHECK-NEXT: .param .align 8 .b8 param0[8]; +; CHECK-NEXT: st.param.v4.b16 [param0+0], {%rs1, 2, 3, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i16, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 52 +; CHECK-NEXT: ret; + %struct.riii0 = insertvalue %struct.short4 poison, i16 %a, 0 + %struct.riii1 = insertvalue %struct.short4 %struct.riii0, i16 2, 1 + %struct.riii2 = insertvalue %struct.short4 %struct.riii1, i16 3, 2 + %struct.riii3 = insertvalue %struct.short4 %struct.riii2, i16 4, 3 + call void @call_v4_i16(%struct.short4 %struct.riii3) + ret void +} + +define void @st_param_v4_i32_iiii() { +; CHECK-LABEL: st_param_v4_i32_iiii( +; CHECK: { +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: { // callseq 53, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.b32 [param0+0], {1, 2, 3, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 53 +; CHECK-NEXT: ret; + call void @call_v4_i32(%struct.int4 { i32 1, i32 2, i32 3, i32 4 }) + ret void +} +define void @st_param_v4_i32_irrr(i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: st_param_v4_i32_irrr( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [st_param_v4_i32_irrr_param_0]; +; CHECK-NEXT: ld.param.u32 %r2, [st_param_v4_i32_irrr_param_1]; +; CHECK-NEXT: ld.param.u32 %r3, [st_param_v4_i32_irrr_param_2]; +; CHECK-NEXT: { // callseq 54, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.b32 [param0+0], {1, %r1, %r2, %r3}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 54 +; CHECK-NEXT: ret; + %struct.irrr0 = insertvalue %struct.int4 poison, i32 1, 0 + %struct.irrr1 = insertvalue %struct.int4 %struct.irrr0, i32 %b, 1 + %struct.irrr2 = insertvalue %struct.int4 %struct.irrr1, i32 %c, 2 + %struct.irrr3 = insertvalue %struct.int4 %struct.irrr2, i32 %d, 3 + call void @call_v4_i32(%struct.int4 %struct.irrr3) + ret void +} +define void @st_param_v4_i32_rirr(i32 %a, i32 %c, i32 %d) { +; CHECK-LABEL: st_param_v4_i32_rirr( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [st_param_v4_i32_rirr_param_0]; +; CHECK-NEXT: ld.param.u32 %r2, [st_param_v4_i32_rirr_param_1]; +; CHECK-NEXT: ld.param.u32 %r3, [st_param_v4_i32_rirr_param_2]; +; CHECK-NEXT: { // callseq 55, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.b32 [param0+0], {%r1, 2, %r2, %r3}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 55 +; CHECK-NEXT: ret; + %struct.rirr0 = insertvalue %struct.int4 poison, i32 %a, 0 + %struct.rirr1 = insertvalue %struct.int4 %struct.rirr0, i32 2, 1 + %struct.rirr2 = insertvalue %struct.int4 %struct.rirr1, i32 %c, 2 + %struct.rirr3 = insertvalue %struct.int4 %struct.rirr2, i32 %d, 3 + call void @call_v4_i32(%struct.int4 %struct.rirr3) + ret void +} +define void @st_param_v4_i32_rrir(i32 %a, i32 %b, i32 %d) { +; CHECK-LABEL: st_param_v4_i32_rrir( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [st_param_v4_i32_rrir_param_0]; +; CHECK-NEXT: ld.param.u32 %r2, [st_param_v4_i32_rrir_param_1]; +; CHECK-NEXT: ld.param.u32 %r3, [st_param_v4_i32_rrir_param_2]; +; CHECK-NEXT: { // callseq 56, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.b32 [param0+0], {%r1, %r2, 3, %r3}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 56 +; CHECK-NEXT: ret; + %struct.rrir0 = insertvalue %struct.int4 poison, i32 %a, 0 + %struct.rrir1 = insertvalue %struct.int4 %struct.rrir0, i32 %b, 1 + %struct.rrir2 = insertvalue %struct.int4 %struct.rrir1, i32 3, 2 + %struct.rrir3 = insertvalue %struct.int4 %struct.rrir2, i32 %d, 3 + call void @call_v4_i32(%struct.int4 %struct.rrir3) + ret void +} +define void @st_param_v4_i32_rrri(i32 %a, i32 %b, i32 %c) { +; CHECK-LABEL: st_param_v4_i32_rrri( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [st_param_v4_i32_rrri_param_0]; +; CHECK-NEXT: ld.param.u32 %r2, [st_param_v4_i32_rrri_param_1]; +; CHECK-NEXT: ld.param.u32 %r3, [st_param_v4_i32_rrri_param_2]; +; CHECK-NEXT: { // callseq 57, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.b32 [param0+0], {%r1, %r2, %r3, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 57 +; CHECK-NEXT: ret; + %struct.rrri0 = insertvalue %struct.int4 poison, i32 %a, 0 + %struct.rrri1 = insertvalue %struct.int4 %struct.rrri0, i32 %b, 1 + %struct.rrri2 = insertvalue %struct.int4 %struct.rrri1, i32 %c, 2 + %struct.rrri3 = insertvalue %struct.int4 %struct.rrri2, i32 4, 3 + call void @call_v4_i32(%struct.int4 %struct.rrri3) + ret void +} +define void @st_param_v4_i32_iirr(i32 %c, i32 %d) { +; CHECK-LABEL: st_param_v4_i32_iirr( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [st_param_v4_i32_iirr_param_0]; +; CHECK-NEXT: ld.param.u32 %r2, [st_param_v4_i32_iirr_param_1]; +; CHECK-NEXT: { // callseq 58, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.b32 [param0+0], {1, 2, %r1, %r2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 58 +; CHECK-NEXT: ret; + %struct.iirr0 = insertvalue %struct.int4 poison, i32 1, 0 + %struct.iirr1 = insertvalue %struct.int4 %struct.iirr0, i32 2, 1 + %struct.iirr2 = insertvalue %struct.int4 %struct.iirr1, i32 %c, 2 + %struct.iirr3 = insertvalue %struct.int4 %struct.iirr2, i32 %d, 3 + call void @call_v4_i32(%struct.int4 %struct.iirr3) + ret void +} +define void @st_param_v4_i32_irir(i32 %b, i32 %d) { +; CHECK-LABEL: st_param_v4_i32_irir( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [st_param_v4_i32_irir_param_0]; +; CHECK-NEXT: ld.param.u32 %r2, [st_param_v4_i32_irir_param_1]; +; CHECK-NEXT: { // callseq 59, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.b32 [param0+0], {1, %r1, 3, %r2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 59 +; CHECK-NEXT: ret; + %struct.irir0 = insertvalue %struct.int4 poison, i32 1, 0 + %struct.irir1 = insertvalue %struct.int4 %struct.irir0, i32 %b, 1 + %struct.irir2 = insertvalue %struct.int4 %struct.irir1, i32 3, 2 + %struct.irir3 = insertvalue %struct.int4 %struct.irir2, i32 %d, 3 + call void @call_v4_i32(%struct.int4 %struct.irir3) + ret void +} +define void @st_param_v4_i32_irri(i32 %b, i32 %c) { +; CHECK-LABEL: st_param_v4_i32_irri( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [st_param_v4_i32_irri_param_0]; +; CHECK-NEXT: ld.param.u32 %r2, [st_param_v4_i32_irri_param_1]; +; CHECK-NEXT: { // callseq 60, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.b32 [param0+0], {1, %r1, %r2, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 60 +; CHECK-NEXT: ret; + %struct.irri0 = insertvalue %struct.int4 poison, i32 1, 0 + %struct.irri1 = insertvalue %struct.int4 %struct.irri0, i32 %b, 1 + %struct.irri2 = insertvalue %struct.int4 %struct.irri1, i32 %c, 2 + %struct.irri3 = insertvalue %struct.int4 %struct.irri2, i32 4, 3 + call void @call_v4_i32(%struct.int4 %struct.irri3) + ret void +} +define void @st_param_v4_i32_riir(i32 %a, i32 %d) { +; CHECK-LABEL: st_param_v4_i32_riir( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [st_param_v4_i32_riir_param_0]; +; CHECK-NEXT: ld.param.u32 %r2, [st_param_v4_i32_riir_param_1]; +; CHECK-NEXT: { // callseq 61, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.b32 [param0+0], {%r1, 2, 3, %r2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 61 +; CHECK-NEXT: ret; + %struct.riir0 = insertvalue %struct.int4 poison, i32 %a, 0 + %struct.riir1 = insertvalue %struct.int4 %struct.riir0, i32 2, 1 + %struct.riir2 = insertvalue %struct.int4 %struct.riir1, i32 3, 2 + %struct.riir3 = insertvalue %struct.int4 %struct.riir2, i32 %d, 3 + call void @call_v4_i32(%struct.int4 %struct.riir3) + ret void +} +define void @st_param_v4_i32_riri(i32 %a, i32 %c) { +; CHECK-LABEL: st_param_v4_i32_riri( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [st_param_v4_i32_riri_param_0]; +; CHECK-NEXT: ld.param.u32 %r2, [st_param_v4_i32_riri_param_1]; +; CHECK-NEXT: { // callseq 62, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.b32 [param0+0], {%r1, 2, %r2, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 62 +; CHECK-NEXT: ret; + %struct.riri0 = insertvalue %struct.int4 poison, i32 %a, 0 + %struct.riri1 = insertvalue %struct.int4 %struct.riri0, i32 2, 1 + %struct.riri2 = insertvalue %struct.int4 %struct.riri1, i32 %c, 2 + %struct.riri3 = insertvalue %struct.int4 %struct.riri2, i32 4, 3 + call void @call_v4_i32(%struct.int4 %struct.riri3) + ret void +} +define void @st_param_v4_i32_rrii(i32 %a, i32 %b) { +; CHECK-LABEL: st_param_v4_i32_rrii( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [st_param_v4_i32_rrii_param_0]; +; CHECK-NEXT: ld.param.u32 %r2, [st_param_v4_i32_rrii_param_1]; +; CHECK-NEXT: { // callseq 63, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.b32 [param0+0], {%r1, %r2, 3, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 63 +; CHECK-NEXT: ret; + %struct.rrii0 = insertvalue %struct.int4 poison, i32 %a, 0 + %struct.rrii1 = insertvalue %struct.int4 %struct.rrii0, i32 %b, 1 + %struct.rrii2 = insertvalue %struct.int4 %struct.rrii1, i32 3, 2 + %struct.rrii3 = insertvalue %struct.int4 %struct.rrii2, i32 4, 3 + call void @call_v4_i32(%struct.int4 %struct.rrii3) + ret void +} +define void @st_param_v4_i32_iiir(i32 %d) { +; CHECK-LABEL: st_param_v4_i32_iiir( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [st_param_v4_i32_iiir_param_0]; +; CHECK-NEXT: { // callseq 64, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.b32 [param0+0], {1, 2, 3, %r1}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 64 +; CHECK-NEXT: ret; + %struct.iiir0 = insertvalue %struct.int4 poison, i32 1, 0 + %struct.iiir1 = insertvalue %struct.int4 %struct.iiir0, i32 2, 1 + %struct.iiir2 = insertvalue %struct.int4 %struct.iiir1, i32 3, 2 + %struct.iiir3 = insertvalue %struct.int4 %struct.iiir2, i32 %d, 3 + call void @call_v4_i32(%struct.int4 %struct.iiir3) + ret void +} +define void @st_param_v4_i32_iiri(i32 %c) { +; CHECK-LABEL: st_param_v4_i32_iiri( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [st_param_v4_i32_iiri_param_0]; +; CHECK-NEXT: { // callseq 65, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.b32 [param0+0], {1, 2, %r1, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 65 +; CHECK-NEXT: ret; + %struct.iiri0 = insertvalue %struct.int4 poison, i32 1, 0 + %struct.iiri1 = insertvalue %struct.int4 %struct.iiri0, i32 2, 1 + %struct.iiri2 = insertvalue %struct.int4 %struct.iiri1, i32 %c, 2 + %struct.iiri3 = insertvalue %struct.int4 %struct.iiri2, i32 4, 3 + call void @call_v4_i32(%struct.int4 %struct.iiri3) + ret void +} +define void @st_param_v4_i32_irii(i32 %b) { +; CHECK-LABEL: st_param_v4_i32_irii( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [st_param_v4_i32_irii_param_0]; +; CHECK-NEXT: { // callseq 66, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.b32 [param0+0], {1, %r1, 3, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 66 +; CHECK-NEXT: ret; + %struct.irii0 = insertvalue %struct.int4 poison, i32 1, 0 + %struct.irii1 = insertvalue %struct.int4 %struct.irii0, i32 %b, 1 + %struct.irii2 = insertvalue %struct.int4 %struct.irii1, i32 3, 2 + %struct.irii3 = insertvalue %struct.int4 %struct.irii2, i32 4, 3 + call void @call_v4_i32(%struct.int4 %struct.irii3) + ret void +} +define void @st_param_v4_i32_riii(i32 %a) { +; CHECK-LABEL: st_param_v4_i32_riii( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [st_param_v4_i32_riii_param_0]; +; CHECK-NEXT: { // callseq 67, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.b32 [param0+0], {%r1, 2, 3, 4}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_i32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 67 +; CHECK-NEXT: ret; + %struct.riii0 = insertvalue %struct.int4 poison, i32 %a, 0 + %struct.riii1 = insertvalue %struct.int4 %struct.riii0, i32 2, 1 + %struct.riii2 = insertvalue %struct.int4 %struct.riii1, i32 3, 2 + %struct.riii3 = insertvalue %struct.int4 %struct.riii2, i32 4, 3 + call void @call_v4_i32(%struct.int4 %struct.riii3) + ret void +} + +define void @st_param_v4_f32_iiii() { +; CHECK-LABEL: st_param_v4_f32_iiii( +; CHECK: { +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: { // callseq 68, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.f32 [param0+0], {0f3F800000, 0f40000000, 0f40400000, 0f40800000}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 68 +; CHECK-NEXT: ret; + call void @call_v4_f32(%struct.float4 { float 1.0, float 2.0, float 3.0, float 4.0 }) + ret void +} +define void @st_param_v4_f32_irrr(float %b, float %c, float %d) { +; CHECK-LABEL: st_param_v4_f32_irrr( +; CHECK: { +; CHECK-NEXT: .reg .f32 %f<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f32 %f1, [st_param_v4_f32_irrr_param_0]; +; CHECK-NEXT: ld.param.f32 %f2, [st_param_v4_f32_irrr_param_1]; +; CHECK-NEXT: ld.param.f32 %f3, [st_param_v4_f32_irrr_param_2]; +; CHECK-NEXT: { // callseq 69, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.f32 [param0+0], {0f3F800000, %f1, %f2, %f3}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 69 +; CHECK-NEXT: ret; + %struct.irrr0 = insertvalue %struct.float4 poison, float 1.0, 0 + %struct.irrr1 = insertvalue %struct.float4 %struct.irrr0, float %b, 1 + %struct.irrr2 = insertvalue %struct.float4 %struct.irrr1, float %c, 2 + %struct.irrr3 = insertvalue %struct.float4 %struct.irrr2, float %d, 3 + call void @call_v4_f32(%struct.float4 %struct.irrr3) + ret void +} +define void @st_param_v4_f32_rirr(float %a, float %c, float %d) { +; CHECK-LABEL: st_param_v4_f32_rirr( +; CHECK: { +; CHECK-NEXT: .reg .f32 %f<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f32 %f1, [st_param_v4_f32_rirr_param_0]; +; CHECK-NEXT: ld.param.f32 %f2, [st_param_v4_f32_rirr_param_1]; +; CHECK-NEXT: ld.param.f32 %f3, [st_param_v4_f32_rirr_param_2]; +; CHECK-NEXT: { // callseq 70, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.f32 [param0+0], {%f1, 0f40000000, %f2, %f3}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 70 +; CHECK-NEXT: ret; + %struct.rirr0 = insertvalue %struct.float4 poison, float %a, 0 + %struct.rirr1 = insertvalue %struct.float4 %struct.rirr0, float 2.0, 1 + %struct.rirr2 = insertvalue %struct.float4 %struct.rirr1, float %c, 2 + %struct.rirr3 = insertvalue %struct.float4 %struct.rirr2, float %d, 3 + call void @call_v4_f32(%struct.float4 %struct.rirr3) + ret void +} +define void @st_param_v4_f32_rrir(float %a, float %b, float %d) { +; CHECK-LABEL: st_param_v4_f32_rrir( +; CHECK: { +; CHECK-NEXT: .reg .f32 %f<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f32 %f1, [st_param_v4_f32_rrir_param_0]; +; CHECK-NEXT: ld.param.f32 %f2, [st_param_v4_f32_rrir_param_1]; +; CHECK-NEXT: ld.param.f32 %f3, [st_param_v4_f32_rrir_param_2]; +; CHECK-NEXT: { // callseq 71, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.f32 [param0+0], {%f1, %f2, 0f40400000, %f3}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 71 +; CHECK-NEXT: ret; + %struct.rrir0 = insertvalue %struct.float4 poison, float %a, 0 + %struct.rrir1 = insertvalue %struct.float4 %struct.rrir0, float %b, 1 + %struct.rrir2 = insertvalue %struct.float4 %struct.rrir1, float 3.0, 2 + %struct.rrir3 = insertvalue %struct.float4 %struct.rrir2, float %d, 3 + call void @call_v4_f32(%struct.float4 %struct.rrir3) + ret void +} +define void @st_param_v4_f32_rrri(float %a, float %b, float %c) { +; CHECK-LABEL: st_param_v4_f32_rrri( +; CHECK: { +; CHECK-NEXT: .reg .f32 %f<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f32 %f1, [st_param_v4_f32_rrri_param_0]; +; CHECK-NEXT: ld.param.f32 %f2, [st_param_v4_f32_rrri_param_1]; +; CHECK-NEXT: ld.param.f32 %f3, [st_param_v4_f32_rrri_param_2]; +; CHECK-NEXT: { // callseq 72, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.f32 [param0+0], {%f1, %f2, %f3, 0f40800000}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 72 +; CHECK-NEXT: ret; + %struct.rrri0 = insertvalue %struct.float4 poison, float %a, 0 + %struct.rrri1 = insertvalue %struct.float4 %struct.rrri0, float %b, 1 + %struct.rrri2 = insertvalue %struct.float4 %struct.rrri1, float %c, 2 + %struct.rrri3 = insertvalue %struct.float4 %struct.rrri2, float 4.0, 3 + call void @call_v4_f32(%struct.float4 %struct.rrri3) + ret void +} +define void @st_param_v4_f32_iirr(float %c, float %d) { +; CHECK-LABEL: st_param_v4_f32_iirr( +; CHECK: { +; CHECK-NEXT: .reg .f32 %f<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f32 %f1, [st_param_v4_f32_iirr_param_0]; +; CHECK-NEXT: ld.param.f32 %f2, [st_param_v4_f32_iirr_param_1]; +; CHECK-NEXT: { // callseq 73, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.f32 [param0+0], {0f3F800000, 0f40000000, %f1, %f2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 73 +; CHECK-NEXT: ret; + %struct.iirr0 = insertvalue %struct.float4 poison, float 1.0, 0 + %struct.iirr1 = insertvalue %struct.float4 %struct.iirr0, float 2.0, 1 + %struct.iirr2 = insertvalue %struct.float4 %struct.iirr1, float %c, 2 + %struct.iirr3 = insertvalue %struct.float4 %struct.iirr2, float %d, 3 + call void @call_v4_f32(%struct.float4 %struct.iirr3) + ret void +} +define void @st_param_v4_f32_irir(float %b, float %d) { +; CHECK-LABEL: st_param_v4_f32_irir( +; CHECK: { +; CHECK-NEXT: .reg .f32 %f<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f32 %f1, [st_param_v4_f32_irir_param_0]; +; CHECK-NEXT: ld.param.f32 %f2, [st_param_v4_f32_irir_param_1]; +; CHECK-NEXT: { // callseq 74, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.f32 [param0+0], {0f3F800000, %f1, 0f40400000, %f2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 74 +; CHECK-NEXT: ret; + %struct.irir0 = insertvalue %struct.float4 poison, float 1.0, 0 + %struct.irir1 = insertvalue %struct.float4 %struct.irir0, float %b, 1 + %struct.irir2 = insertvalue %struct.float4 %struct.irir1, float 3.0, 2 + %struct.irir3 = insertvalue %struct.float4 %struct.irir2, float %d, 3 + call void @call_v4_f32(%struct.float4 %struct.irir3) + ret void +} +define void @st_param_v4_f32_irri(float %b, float %c) { +; CHECK-LABEL: st_param_v4_f32_irri( +; CHECK: { +; CHECK-NEXT: .reg .f32 %f<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f32 %f1, [st_param_v4_f32_irri_param_0]; +; CHECK-NEXT: ld.param.f32 %f2, [st_param_v4_f32_irri_param_1]; +; CHECK-NEXT: { // callseq 75, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.f32 [param0+0], {0f3F800000, %f1, %f2, 0f40800000}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 75 +; CHECK-NEXT: ret; + %struct.irri0 = insertvalue %struct.float4 poison, float 1.0, 0 + %struct.irri1 = insertvalue %struct.float4 %struct.irri0, float %b, 1 + %struct.irri2 = insertvalue %struct.float4 %struct.irri1, float %c, 2 + %struct.irri3 = insertvalue %struct.float4 %struct.irri2, float 4.0, 3 + call void @call_v4_f32(%struct.float4 %struct.irri3) + ret void +} +define void @st_param_v4_f32_riir(float %a, float %d) { +; CHECK-LABEL: st_param_v4_f32_riir( +; CHECK: { +; CHECK-NEXT: .reg .f32 %f<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f32 %f1, [st_param_v4_f32_riir_param_0]; +; CHECK-NEXT: ld.param.f32 %f2, [st_param_v4_f32_riir_param_1]; +; CHECK-NEXT: { // callseq 76, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.f32 [param0+0], {%f1, 0f40000000, 0f40400000, %f2}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 76 +; CHECK-NEXT: ret; + %struct.riir0 = insertvalue %struct.float4 poison, float %a, 0 + %struct.riir1 = insertvalue %struct.float4 %struct.riir0, float 2.0, 1 + %struct.riir2 = insertvalue %struct.float4 %struct.riir1, float 3.0, 2 + %struct.riir3 = insertvalue %struct.float4 %struct.riir2, float %d, 3 + call void @call_v4_f32(%struct.float4 %struct.riir3) + ret void +} +define void @st_param_v4_f32_riri(float %a, float %c) { +; CHECK-LABEL: st_param_v4_f32_riri( +; CHECK: { +; CHECK-NEXT: .reg .f32 %f<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f32 %f1, [st_param_v4_f32_riri_param_0]; +; CHECK-NEXT: ld.param.f32 %f2, [st_param_v4_f32_riri_param_1]; +; CHECK-NEXT: { // callseq 77, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.f32 [param0+0], {%f1, 0f40000000, %f2, 0f40800000}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 77 +; CHECK-NEXT: ret; + %struct.riri0 = insertvalue %struct.float4 poison, float %a, 0 + %struct.riri1 = insertvalue %struct.float4 %struct.riri0, float 2.0, 1 + %struct.riri2 = insertvalue %struct.float4 %struct.riri1, float %c, 2 + %struct.riri3 = insertvalue %struct.float4 %struct.riri2, float 4.0, 3 + call void @call_v4_f32(%struct.float4 %struct.riri3) + ret void +} +define void @st_param_v4_f32_rrii(float %a, float %b) { +; CHECK-LABEL: st_param_v4_f32_rrii( +; CHECK: { +; CHECK-NEXT: .reg .f32 %f<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f32 %f1, [st_param_v4_f32_rrii_param_0]; +; CHECK-NEXT: ld.param.f32 %f2, [st_param_v4_f32_rrii_param_1]; +; CHECK-NEXT: { // callseq 78, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.f32 [param0+0], {%f1, %f2, 0f40400000, 0f40800000}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 78 +; CHECK-NEXT: ret; + %struct.rrii0 = insertvalue %struct.float4 poison, float %a, 0 + %struct.rrii1 = insertvalue %struct.float4 %struct.rrii0, float %b, 1 + %struct.rrii2 = insertvalue %struct.float4 %struct.rrii1, float 3.0, 2 + %struct.rrii3 = insertvalue %struct.float4 %struct.rrii2, float 4.0, 3 + call void @call_v4_f32(%struct.float4 %struct.rrii3) + ret void +} +define void @st_param_v4_f32_iiir(float %d) { +; CHECK-LABEL: st_param_v4_f32_iiir( +; CHECK: { +; CHECK-NEXT: .reg .f32 %f<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f32 %f1, [st_param_v4_f32_iiir_param_0]; +; CHECK-NEXT: { // callseq 79, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.f32 [param0+0], {0f3F800000, 0f40000000, 0f40400000, %f1}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 79 +; CHECK-NEXT: ret; + %struct.iiir0 = insertvalue %struct.float4 poison, float 1.0, 0 + %struct.iiir1 = insertvalue %struct.float4 %struct.iiir0, float 2.0, 1 + %struct.iiir2 = insertvalue %struct.float4 %struct.iiir1, float 3.0, 2 + %struct.iiir3 = insertvalue %struct.float4 %struct.iiir2, float %d, 3 + call void @call_v4_f32(%struct.float4 %struct.iiir3) + ret void +} +define void @st_param_v4_f32_iiri(float %c) { +; CHECK-LABEL: st_param_v4_f32_iiri( +; CHECK: { +; CHECK-NEXT: .reg .f32 %f<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f32 %f1, [st_param_v4_f32_iiri_param_0]; +; CHECK-NEXT: { // callseq 80, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.f32 [param0+0], {0f3F800000, 0f40000000, %f1, 0f40800000}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 80 +; CHECK-NEXT: ret; + %struct.iiri0 = insertvalue %struct.float4 poison, float 1.0, 0 + %struct.iiri1 = insertvalue %struct.float4 %struct.iiri0, float 2.0, 1 + %struct.iiri2 = insertvalue %struct.float4 %struct.iiri1, float %c, 2 + %struct.iiri3 = insertvalue %struct.float4 %struct.iiri2, float 4.0, 3 + call void @call_v4_f32(%struct.float4 %struct.iiri3) + ret void +} +define void @st_param_v4_f32_irii(float %b) { +; CHECK-LABEL: st_param_v4_f32_irii( +; CHECK: { +; CHECK-NEXT: .reg .f32 %f<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f32 %f1, [st_param_v4_f32_irii_param_0]; +; CHECK-NEXT: { // callseq 81, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.f32 [param0+0], {0f3F800000, %f1, 0f40400000, 0f40800000}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 81 +; CHECK-NEXT: ret; + %struct.irii0 = insertvalue %struct.float4 poison, float 1.0, 0 + %struct.irii1 = insertvalue %struct.float4 %struct.irii0, float %b, 1 + %struct.irii2 = insertvalue %struct.float4 %struct.irii1, float 3.0, 2 + %struct.irii3 = insertvalue %struct.float4 %struct.irii2, float 4.0, 3 + call void @call_v4_f32(%struct.float4 %struct.irii3) + ret void +} +define void @st_param_v4_f32_riii(float %a) { +; CHECK-LABEL: st_param_v4_f32_riii( +; CHECK: { +; CHECK-NEXT: .reg .f32 %f<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.f32 %f1, [st_param_v4_f32_riii_param_0]; +; CHECK-NEXT: { // callseq 82, 0 +; CHECK-NEXT: .param .align 16 .b8 param0[16]; +; CHECK-NEXT: st.param.v4.f32 [param0+0], {%f1, 0f40000000, 0f40400000, 0f40800000}; +; CHECK-NEXT: call.uni +; CHECK-NEXT: call_v4_f32, +; CHECK-NEXT: ( +; CHECK-NEXT: param0 +; CHECK-NEXT: ); +; CHECK-NEXT: } // callseq 82 +; CHECK-NEXT: ret; + %struct.riii0 = insertvalue %struct.float4 poison, float %a, 0 + %struct.riii1 = insertvalue %struct.float4 %struct.riii0, float 2.0, 1 + %struct.riii2 = insertvalue %struct.float4 %struct.riii1, float 3.0, 2 + %struct.riii3 = insertvalue %struct.float4 %struct.riii2, float 4.0, 3 + call void @call_v4_f32(%struct.float4 %struct.riii3) + ret void +} + +declare void @call_v4_i8(%struct.char4 alignstack(4)) +declare void @call_v4_i16(%struct.short4 alignstack(8)) +declare void @call_v4_i32(%struct.int4 alignstack(16)) +declare void @call_v4_f32(%struct.float4 alignstack(16)) -- GitLab From 577785c5ca78a9714584b5c99ec085f8aea0a5c0 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sat, 18 May 2024 18:43:20 +0100 Subject: [PATCH 002/793] [VPlan] Remove unused removeLastOperand (NFC). The last use of the function has been removed a while ago. Remove the unused function. --- llvm/lib/Transforms/Vectorize/VPlanValue.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VPlanValue.h b/llvm/lib/Transforms/Vectorize/VPlanValue.h index 96d04271850f..8d945f6f2b8e 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanValue.h +++ b/llvm/lib/Transforms/Vectorize/VPlanValue.h @@ -261,11 +261,6 @@ public: New->addUser(*this); } - void removeLastOperand() { - VPValue *Op = Operands.pop_back_val(); - Op->removeUser(*this); - } - typedef SmallVectorImpl::iterator operand_iterator; typedef SmallVectorImpl::const_iterator const_operand_iterator; typedef iterator_range operand_range; -- GitLab From 003cebdaccc4ad3a3b6f9e177ee5049c8b6a9cbb Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Sat, 18 May 2024 11:29:21 -0700 Subject: [PATCH 003/793] [dsymutil] Use operator==(StringRef, StringRef) (NFC) --- llvm/tools/dsymutil/MachODebugMapParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/tools/dsymutil/MachODebugMapParser.cpp b/llvm/tools/dsymutil/MachODebugMapParser.cpp index 6a9f25681cdd..e28c976d6ace 100644 --- a/llvm/tools/dsymutil/MachODebugMapParser.cpp +++ b/llvm/tools/dsymutil/MachODebugMapParser.cpp @@ -301,7 +301,7 @@ void MachODebugMapParser::switchToNewLibDebugMapObject( if (CurrentDebugMapObject && CurrentDebugMapObject->getType() == MachO::N_LIB && - CurrentDebugMapObject->getObjectFilename().compare(Path.str()) == 0) { + CurrentDebugMapObject->getObjectFilename() == Path) { return; } -- GitLab From 8d3e1022c8883f2bfe9faccb82ce807c1cf4272c Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Sat, 18 May 2024 11:39:23 -0700 Subject: [PATCH 004/793] [DWARFLinker] Use an implicit conversion of SmallString to StringRef (NFC) --- llvm/lib/DWARFLinker/Parallel/OutputSections.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/DWARFLinker/Parallel/OutputSections.h b/llvm/lib/DWARFLinker/Parallel/OutputSections.h index 0e1f2dae54bc..d2e4622aa764 100644 --- a/llvm/lib/DWARFLinker/Parallel/OutputSections.h +++ b/llvm/lib/DWARFLinker/Parallel/OutputSections.h @@ -220,7 +220,7 @@ struct SectionDescriptor : SectionDescriptorBase { /// Returns section content. StringRef getContents() override { if (SectionOffsetInsideAsmPrinterOutputStart == 0) - return StringRef(Contents.data(), Contents.size()); + return Contents; return Contents.slice(SectionOffsetInsideAsmPrinterOutputStart, SectionOffsetInsideAsmPrinterOutputEnd); -- GitLab From ba8a2ade84f4c1bfc531fe3673470377c038f31d Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Sat, 18 May 2024 20:53:21 +0100 Subject: [PATCH 005/793] [DXIL] Use consistent SmallVector parameters Fixes: 060df78cdbbf70d5a6dfff3af1d435a5a811b886 --- llvm/lib/Target/DirectX/DXILOpLowering.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index f09e322f88e1..1329308ffec2 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -41,7 +41,7 @@ static bool isVectorArgExpansion(Function &F) { } static SmallVector populateOperands(Value *Arg, IRBuilder<> &Builder) { - SmallVector ExtractedElements; + SmallVector ExtractedElements; auto *VecArg = dyn_cast(Arg->getType()); for (unsigned I = 0; I < VecArg->getNumElements(); ++I) { Value *Index = ConstantInt::get(Type::getInt32Ty(Arg->getContext()), I); -- GitLab From 4c98f5b439ddd204d8ff1e423104215ebd0e1720 Mon Sep 17 00:00:00 2001 From: David Green Date: Sat, 18 May 2024 22:50:19 +0100 Subject: [PATCH 006/793] [DAG] Use copysign in frem power-2 fold. (#91751) As a small addition to #91148, this uses copysign to produce the correct sign for zero when converting frem to div/trunc/mul when we do not know that the input is positive (and we care about sign bits). The copysign lets us get the sign of zero correct. In testing, the only case this produced different results than fmod was: frem -inf, 4.0 -> nan vs -nan --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 19 ++-- llvm/test/CodeGen/AArch64/frem-power2.ll | 92 +++++++++++++++++-- llvm/test/CodeGen/ARM/frem-power2.ll | 24 ++++- 3 files changed, 117 insertions(+), 18 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 2b181cd3ab1d..2b1dec8205b7 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -17386,15 +17386,20 @@ SDValue DAGCombiner::visitFREM(SDNode *N) { TLI.isOperationLegalOrCustom(ISD::FMUL, VT) && TLI.isOperationLegalOrCustom(ISD::FDIV, VT) && TLI.isOperationLegalOrCustom(ISD::FTRUNC, VT) && - DAG.isKnownToBeAPowerOfTwoFP(N1) && - (Flags.hasNoSignedZeros() || DAG.cannotBeOrderedNegativeFP(N0))) { + DAG.isKnownToBeAPowerOfTwoFP(N1)) { + bool NeedsCopySign = + !Flags.hasNoSignedZeros() && !DAG.cannotBeOrderedNegativeFP(N0); SDValue Div = DAG.getNode(ISD::FDIV, DL, VT, N0, N1); SDValue Rnd = DAG.getNode(ISD::FTRUNC, DL, VT, Div); - if (TLI.isFMAFasterThanFMulAndFAdd(DAG.getMachineFunction(), VT)) - return DAG.getNode(ISD::FMA, DL, VT, DAG.getNode(ISD::FNEG, DL, VT, Rnd), - N1, N0); - SDValue Mul = DAG.getNode(ISD::FMUL, DL, VT, Rnd, N1); - return DAG.getNode(ISD::FSUB, DL, VT, N0, Mul); + SDValue MLA; + if (TLI.isFMAFasterThanFMulAndFAdd(DAG.getMachineFunction(), VT)) { + MLA = DAG.getNode(ISD::FMA, DL, VT, DAG.getNode(ISD::FNEG, DL, VT, Rnd), + N1, N0); + } else { + SDValue Mul = DAG.getNode(ISD::FMUL, DL, VT, Rnd, N1); + MLA = DAG.getNode(ISD::FSUB, DL, VT, N0, Mul); + } + return NeedsCopySign ? DAG.getNode(ISD::FCOPYSIGN, DL, VT, MLA, N0) : MLA; } return SDValue(); diff --git a/llvm/test/CodeGen/AArch64/frem-power2.ll b/llvm/test/CodeGen/AArch64/frem-power2.ll index 402e03c5e265..4192745abd34 100644 --- a/llvm/test/CodeGen/AArch64/frem-power2.ll +++ b/llvm/test/CodeGen/AArch64/frem-power2.ll @@ -3,10 +3,22 @@ ; RUN: llc -mtriple=aarch64 -mattr=+fullfp16 -global-isel -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI define float @frem2(float %x) { -; CHECK-LABEL: frem2: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: fmov s1, #2.00000000 -; CHECK-NEXT: b fmodf +; CHECK-SD-LABEL: frem2: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: fmov s1, #2.00000000 +; CHECK-SD-NEXT: // kill: def $s0 killed $s0 def $q0 +; CHECK-SD-NEXT: fdiv s2, s0, s1 +; CHECK-SD-NEXT: frintz s2, s2 +; CHECK-SD-NEXT: fmsub s1, s2, s1, s0 +; CHECK-SD-NEXT: mvni v2.4s, #128, lsl #24 +; CHECK-SD-NEXT: bit v0.16b, v1.16b, v2.16b +; CHECK-SD-NEXT: // kill: def $s0 killed $s0 killed $q0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: frem2: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: fmov s1, #2.00000000 +; CHECK-GI-NEXT: b fmodf entry: %fmod = frem float %x, 2.0 ret float %fmod @@ -311,6 +323,67 @@ entry: ret float %fmod } +define <4 x float> @frem2_vec(<4 x float> %x) { +; CHECK-SD-LABEL: frem2_vec: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: movi v1.4s, #64, lsl #24 +; CHECK-SD-NEXT: mov v3.16b, v0.16b +; CHECK-SD-NEXT: fdiv v2.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: frintz v2.4s, v2.4s +; CHECK-SD-NEXT: fmls v3.4s, v1.4s, v2.4s +; CHECK-SD-NEXT: mvni v1.4s, #128, lsl #24 +; CHECK-SD-NEXT: bit v0.16b, v3.16b, v1.16b +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: frem2_vec: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #80 +; CHECK-GI-NEXT: str d10, [sp, #48] // 8-byte Folded Spill +; CHECK-GI-NEXT: stp d9, d8, [sp, #56] // 16-byte Folded Spill +; CHECK-GI-NEXT: str x30, [sp, #72] // 8-byte Folded Spill +; CHECK-GI-NEXT: .cfi_def_cfa_offset 80 +; CHECK-GI-NEXT: .cfi_offset w30, -8 +; CHECK-GI-NEXT: .cfi_offset b8, -16 +; CHECK-GI-NEXT: .cfi_offset b9, -24 +; CHECK-GI-NEXT: .cfi_offset b10, -32 +; CHECK-GI-NEXT: fmov s1, #2.00000000 +; CHECK-GI-NEXT: mov s8, v0.s[1] +; CHECK-GI-NEXT: mov s9, v0.s[2] +; CHECK-GI-NEXT: mov s10, v0.s[3] +; CHECK-GI-NEXT: // kill: def $s0 killed $s0 killed $q0 +; CHECK-GI-NEXT: bl fmodf +; CHECK-GI-NEXT: // kill: def $s0 killed $s0 def $q0 +; CHECK-GI-NEXT: str q0, [sp, #32] // 16-byte Folded Spill +; CHECK-GI-NEXT: fmov s1, #2.00000000 +; CHECK-GI-NEXT: fmov s0, s8 +; CHECK-GI-NEXT: bl fmodf +; CHECK-GI-NEXT: // kill: def $s0 killed $s0 def $q0 +; CHECK-GI-NEXT: str q0, [sp, #16] // 16-byte Folded Spill +; CHECK-GI-NEXT: fmov s1, #2.00000000 +; CHECK-GI-NEXT: fmov s0, s9 +; CHECK-GI-NEXT: bl fmodf +; CHECK-GI-NEXT: // kill: def $s0 killed $s0 def $q0 +; CHECK-GI-NEXT: str q0, [sp] // 16-byte Folded Spill +; CHECK-GI-NEXT: fmov s1, #2.00000000 +; CHECK-GI-NEXT: fmov s0, s10 +; CHECK-GI-NEXT: bl fmodf +; CHECK-GI-NEXT: ldp q2, q1, [sp, #16] // 32-byte Folded Reload +; CHECK-GI-NEXT: // kill: def $s0 killed $s0 def $q0 +; CHECK-GI-NEXT: ldr x30, [sp, #72] // 8-byte Folded Reload +; CHECK-GI-NEXT: ldp d9, d8, [sp, #56] // 16-byte Folded Reload +; CHECK-GI-NEXT: ldr d10, [sp, #48] // 8-byte Folded Reload +; CHECK-GI-NEXT: mov v1.s[1], v2.s[0] +; CHECK-GI-NEXT: ldr q2, [sp] // 16-byte Folded Reload +; CHECK-GI-NEXT: mov v1.s[2], v2.s[0] +; CHECK-GI-NEXT: mov v1.s[3], v0.s[0] +; CHECK-GI-NEXT: mov v0.16b, v1.16b +; CHECK-GI-NEXT: add sp, sp, #80 +; CHECK-GI-NEXT: ret +entry: + %fmod = frem <4 x float> %x, + ret <4 x float> %fmod +} + define <4 x float> @frem2_nsz_vec(<4 x float> %x) { ; CHECK-SD-LABEL: frem2_nsz_vec: ; CHECK-SD: // %bb.0: // %entry @@ -514,10 +587,15 @@ define float @frem2_constneg_sitofp(float %x, i32 %sa) { ; CHECK-SD-LABEL: frem2_constneg_sitofp: ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: mov w8, #1 // =0x1 -; CHECK-SD-NEXT: fmov s0, #-12.50000000 +; CHECK-SD-NEXT: fmov s1, #-12.50000000 ; CHECK-SD-NEXT: lsl w8, w8, w0 -; CHECK-SD-NEXT: scvtf s1, w8 -; CHECK-SD-NEXT: b fmodf +; CHECK-SD-NEXT: scvtf s0, w8 +; CHECK-SD-NEXT: fdiv s2, s1, s0 +; CHECK-SD-NEXT: frintz s2, s2 +; CHECK-SD-NEXT: fmsub s0, s2, s0, s1 +; CHECK-SD-NEXT: fabs s0, s0 +; CHECK-SD-NEXT: fneg s0, s0 +; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: frem2_constneg_sitofp: ; CHECK-GI: // %bb.0: // %entry diff --git a/llvm/test/CodeGen/ARM/frem-power2.ll b/llvm/test/CodeGen/ARM/frem-power2.ll index 7f52943175ac..71c2c09c0105 100644 --- a/llvm/test/CodeGen/ARM/frem-power2.ll +++ b/llvm/test/CodeGen/ARM/frem-power2.ll @@ -14,13 +14,29 @@ define float @frem4(float %x) { ; ; CHECK-FP-LABEL: frem4: ; CHECK-FP: @ %bb.0: @ %entry -; CHECK-FP-NEXT: mov.w r1, #1082130432 -; CHECK-FP-NEXT: b fmodf +; CHECK-FP-NEXT: vmov.f32 s0, #4.000000e+00 +; CHECK-FP-NEXT: vmov s2, r0 +; CHECK-FP-NEXT: lsrs r0, r0, #31 +; CHECK-FP-NEXT: vdiv.f32 s4, s2, s0 +; CHECK-FP-NEXT: vrintz.f32 s4, s4 +; CHECK-FP-NEXT: vfms.f32 s2, s4, s0 +; CHECK-FP-NEXT: vmov r1, s2 +; CHECK-FP-NEXT: bfi r1, r0, #31, #1 +; CHECK-FP-NEXT: mov r0, r1 +; CHECK-FP-NEXT: bx lr ; ; CHECK-M33-LABEL: frem4: ; CHECK-M33: @ %bb.0: @ %entry -; CHECK-M33-NEXT: mov.w r1, #1082130432 -; CHECK-M33-NEXT: b fmodf +; CHECK-M33-NEXT: vmov.f32 s0, #4.000000e+00 +; CHECK-M33-NEXT: vmov s2, r0 +; CHECK-M33-NEXT: lsrs r0, r0, #31 +; CHECK-M33-NEXT: vdiv.f32 s4, s2, s0 +; CHECK-M33-NEXT: vrintz.f32 s4, s4 +; CHECK-M33-NEXT: vmls.f32 s2, s4, s0 +; CHECK-M33-NEXT: vmov r1, s2 +; CHECK-M33-NEXT: bfi r1, r0, #31, #1 +; CHECK-M33-NEXT: mov r0, r1 +; CHECK-M33-NEXT: bx lr entry: %fmod = frem float %x, 4.0 ret float %fmod -- GitLab From c3677e45222a9461eed0224b99bd8ea19bc52bf6 Mon Sep 17 00:00:00 2001 From: David Green Date: Sat, 18 May 2024 23:37:55 +0100 Subject: [PATCH 007/793] [VectorCombine] Don't transform single shuffles in shuffleToIdentity This will help in later patches where the checks for operands being instructions is removed, and might help not remove unnecessary poison lanes. --- llvm/lib/Transforms/Vectorize/VectorCombine.cpp | 3 +++ llvm/test/Transforms/VectorCombine/X86/select-shuffle.ll | 9 +++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp index 9d43fb4ab607..15deaf908422 100644 --- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp @@ -1794,6 +1794,9 @@ bool VectorCombine::foldShuffleToIdentity(Instruction &I) { } } + if (NumVisited <= 1) + return false; + // If we got this far, we know the shuffles are superfluous and can be // removed. Scan through again and generate the new tree of instructions. std::function)> Generate = diff --git a/llvm/test/Transforms/VectorCombine/X86/select-shuffle.ll b/llvm/test/Transforms/VectorCombine/X86/select-shuffle.ll index 60a6c4b1d9b9..685d661ea6bc 100644 --- a/llvm/test/Transforms/VectorCombine/X86/select-shuffle.ll +++ b/llvm/test/Transforms/VectorCombine/X86/select-shuffle.ll @@ -12,11 +12,12 @@ define <4 x double> @PR60649() { ; CHECK: unreachable: ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[TMP0:%.*]] = phi <4 x double> [ zeroinitializer, [[ENTRY:%.*]] ], [ zeroinitializer, [[UNREACHABLE:%.*]] ] +; CHECK-NEXT: [[T0:%.*]] = phi <4 x double> [ zeroinitializer, [[ENTRY:%.*]] ], [ zeroinitializer, [[UNREACHABLE:%.*]] ] ; CHECK-NEXT: [[T1:%.*]] = phi <4 x double> [ zeroinitializer, [[ENTRY]] ], [ zeroinitializer, [[UNREACHABLE]] ] -; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x double> [[TMP0]], <4 x double> [[TMP0]], <4 x i32> -; CHECK-NEXT: [[TMP2:%.*]] = fdiv <4 x double> [[TMP0]], -; CHECK-NEXT: [[TMP3:%.*]] = fmul <4 x double> [[TMP1]], +; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <4 x double> [[T0]], <4 x double> [[T0]], <4 x i32> +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x double> [[T0]], <4 x double> [[T0]], <4 x i32> +; CHECK-NEXT: [[TMP2:%.*]] = fdiv <4 x double> [[TMP1]], +; CHECK-NEXT: [[TMP3:%.*]] = fmul <4 x double> [[TMP0]], ; CHECK-NEXT: [[T5:%.*]] = shufflevector <4 x double> [[TMP2]], <4 x double> [[TMP3]], <4 x i32> ; CHECK-NEXT: ret <4 x double> [[T5]] ; -- GitLab From 597ac471cc7da97ccf957362a7e9f7a52d6910ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolai=20H=C3=A4hnle?= Date: Sun, 19 May 2024 01:39:47 +0200 Subject: [PATCH 008/793] update_test_checks: match IR basic block labels (#88979) Labels are matched using a regexp of the form '^(pattern):', which requires the addition of a "suffix" concept to NamelessValue. Aside from that, the key challenge is that block labels are values, and we typically capture values including the prefix '%'. However, when labels appear at the start of a basic block, the prefix '%' is not included, so we must capture block label values *without* the prefix '%'. We don't know ahead of time whether an IR value is a label or not. In most cases, they are prefixed by the word "label" (their type), but this isn't the case in phi nodes. We solve this issue by leveraging the two-phase nature of variable generalization: the first pass finds all occurences of a variable and determines whether the '%' prefix can be included or not. The second pass does the actual substitution. This change also unifies the generalization path for assembly with that for IR and analysis, in the hope that any future changes avoid diverging those cases future. I also considered the alternative of trying to detect the phi node case using more regular expression special cases but ultimately decided against that because it seemed more fragile, and perhaps the approach of keeping a tentative prefix that may later be discarded could also be eventually applied to some metadata and attribute cases. Note that an early version of this change was reviewed as https://reviews.llvm.org/D142452, before version numbers were introduced. This is a substantially updated version of that change. --- .../Inputs/phi-labels.ll.expected | 36 +- .../update_test_checks/phi-labels.test | 2 +- llvm/utils/UpdateTestChecks/asm.py | 5 +- llvm/utils/UpdateTestChecks/common.py | 925 +++++++++--------- llvm/utils/UpdateTestChecks/isel.py | 5 +- llvm/utils/update_analyze_test_checks.py | 5 +- llvm/utils/update_cc_test_checks.py | 49 +- llvm/utils/update_llc_test_checks.py | 8 +- llvm/utils/update_test_checks.py | 15 +- 9 files changed, 534 insertions(+), 516 deletions(-) diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/phi-labels.ll.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/phi-labels.ll.expected index 1d21ebe547f6..5e70a6c89d32 100644 --- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/phi-labels.ll.expected +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/phi-labels.ll.expected @@ -1,15 +1,15 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 ; RUN: opt < %s -S | FileCheck %s define i32 @phi_after_label(i1 %cc) { ; CHECK-LABEL: define i32 @phi_after_label( ; CHECK-SAME: i1 [[CC:%.*]]) { -; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 [[CC]], label [[THEN:%.*]], label [[END:%.*]] -; CHECK: then: -; CHECK-NEXT: br label [[END]] -; CHECK: end: -; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 1, [[THEN]] ] +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: br i1 [[CC]], label %[[THEN:.*]], label %[[END:.*]] +; CHECK: [[THEN]]: +; CHECK-NEXT: br label %[[END]] +; CHECK: [[END]]: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ 1, %[[THEN]] ] ; CHECK-NEXT: ret i32 [[R]] ; entry: @@ -26,14 +26,14 @@ end: define void @phi_before_label(i32 %bound) { ; CHECK-LABEL: define void @phi_before_label( ; CHECK-SAME: i32 [[BOUND:%.*]]) { -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[LOOP:%.*]] -; CHECK: loop: -; CHECK-NEXT: [[CTR:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[CTR_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK-NEXT: [[CTR:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[CTR_NEXT:%.*]], %[[LOOP]] ] ; CHECK-NEXT: [[CTR_NEXT]] = add i32 [[CTR]], 1 ; CHECK-NEXT: [[CC:%.*]] = icmp ult i32 [[CTR_NEXT]], [[BOUND]] -; CHECK-NEXT: br i1 [[CC]], label [[LOOP]], label [[END:%.*]] -; CHECK: end: +; CHECK-NEXT: br i1 [[CC]], label %[[LOOP]], label %[[END:.*]] +; CHECK: [[END]]: ; CHECK-NEXT: ret void ; entry: @@ -52,11 +52,11 @@ end: define i32 @phi_after_label_unnamed(i1 %cc) { ; CHECK-LABEL: define i32 @phi_after_label_unnamed( ; CHECK-SAME: i1 [[CC:%.*]]) { -; CHECK-NEXT: br i1 [[CC]], label [[TMP1:%.*]], label [[TMP2:%.*]] -; CHECK: 1: -; CHECK-NEXT: br label [[TMP2]] -; CHECK: 2: -; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ 1, [[TMP1]] ] +; CHECK-NEXT: br i1 [[CC]], label %[[BB1:.*]], label %[[BB2:.*]] +; CHECK: [[BB1]]: +; CHECK-NEXT: br label %[[BB2]] +; CHECK: [[BB2]]: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ 1, %[[BB1]] ] ; CHECK-NEXT: ret i32 [[R]] ; 0: diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/phi-labels.test b/llvm/test/tools/UpdateTestChecks/update_test_checks/phi-labels.test index 411c84de1dcb..2b0d0cb7f54b 100644 --- a/llvm/test/tools/UpdateTestChecks/update_test_checks/phi-labels.test +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/phi-labels.test @@ -1,4 +1,4 @@ -# RUN: cp -f %S/Inputs/phi-labels.ll %t.ll && %update_test_checks --version 4 %t.ll +# RUN: cp -f %S/Inputs/phi-labels.ll %t.ll && %update_test_checks --version 5 %t.ll # RUN: diff -u %t.ll %S/Inputs/phi-labels.ll.expected ## Check that running the script again does not change the result: # RUN: %update_test_checks %t.ll diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py index f0c456a1648d..33ede81a4160 100644 --- a/llvm/utils/UpdateTestChecks/asm.py +++ b/llvm/utils/UpdateTestChecks/asm.py @@ -605,6 +605,7 @@ def add_checks( prefix_list, func_dict, func_name, + ginfo: common.GeneralizerInfo, global_vars_seen_dict, is_filtered, ): @@ -617,9 +618,7 @@ def add_checks( func_dict, func_name, check_label_format, - True, - False, - 1, + ginfo, global_vars_seen_dict, is_filtered=is_filtered, ) diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py index 5595e6f41755..7da16e0f0cb2 100644 --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -30,8 +30,9 @@ Version changelog: in case arguments are split to a separate SAME line. 4: --check-globals now has a third option ('smart'). The others are now called 'none' and 'all'. 'smart' is the default. +5: Basic block labels are matched by FileCheck expressions """ -DEFAULT_VERSION = 4 +DEFAULT_VERSION = 5 SUPPORTED_ANALYSES = { @@ -698,6 +699,7 @@ class function_body(object): args_and_sig, attrs, func_name_separator, + ginfo, ): self.scrub = string self.extrascrub = extra @@ -705,24 +707,27 @@ class function_body(object): self.args_and_sig = args_and_sig self.attrs = attrs self.func_name_separator = func_name_separator + self._ginfo = ginfo def is_same_except_arg_names( - self, extrascrub, funcdef_attrs_and_ret, args_and_sig, attrs, is_backend + self, extrascrub, funcdef_attrs_and_ret, args_and_sig, attrs ): arg_names = set() def drop_arg_names(match): - arg_names.add(match.group(variable_group_in_ir_value_match)) - if match.group(attribute_group_in_ir_value_match): - attr = match.group(attribute_group_in_ir_value_match) + nameless_value = self._ginfo.get_nameless_value_from_match(match) + if nameless_value.check_key == "%": + arg_names.add(self._ginfo.get_name_from_match(match)) + substitute = "" else: - attr = "" - return match.group(1) + attr + match.group(match.lastindex) + substitute = match.group(2) + return match.group(1) + substitute + match.group(match.lastindex) def repl_arg_names(match): + nameless_value = self._ginfo.get_nameless_value_from_match(match) if ( - match.group(variable_group_in_ir_value_match) is not None - and match.group(variable_group_in_ir_value_match) in arg_names + nameless_value.check_key == "%" + and self._ginfo.get_name_from_match(match) in arg_names ): return match.group(1) + match.group(match.lastindex) return match.group(1) + match.group(2) + match.group(match.lastindex) @@ -731,17 +736,19 @@ class function_body(object): return False if self.attrs != attrs: return False - ans0 = IR_VALUE_RE.sub(drop_arg_names, self.args_and_sig) - ans1 = IR_VALUE_RE.sub(drop_arg_names, args_and_sig) + + regexp = self._ginfo.get_regexp() + ans0 = regexp.sub(drop_arg_names, self.args_and_sig) + ans1 = regexp.sub(drop_arg_names, args_and_sig) if ans0 != ans1: return False - if is_backend: + if self._ginfo.is_asm(): # Check without replacements, the replacements are not applied to the # body for backend checks. return self.extrascrub == extrascrub - es0 = IR_VALUE_RE.sub(repl_arg_names, self.extrascrub) - es1 = IR_VALUE_RE.sub(repl_arg_names, extrascrub) + es0 = regexp.sub(repl_arg_names, self.extrascrub) + es1 = regexp.sub(repl_arg_names, extrascrub) es0 = SCRUB_IR_COMMENT_RE.sub(r"", es0) es1 = SCRUB_IR_COMMENT_RE.sub(r"", es1) return es0 == es1 @@ -751,7 +758,7 @@ class function_body(object): class FunctionTestBuilder: - def __init__(self, run_list, flags, scrubber_args, path): + def __init__(self, run_list, flags, scrubber_args, path, ginfo): self._verbose = flags.verbose self._record_args = flags.function_signature self._check_attributes = flags.check_attributes @@ -770,6 +777,7 @@ class FunctionTestBuilder: ) self._scrubber_args = scrubber_args self._path = path + self._ginfo = ginfo # Strip double-quotes if input was read by UTC_ARGS self._replace_value_regex = list( map(lambda x: x.strip('"'), flags.replace_value_regex) @@ -804,10 +812,10 @@ class FunctionTestBuilder: def is_filtered(self): return bool(self._filters) - def process_run_line( - self, function_re, scrubber, raw_tool_output, prefixes, is_backend - ): - build_global_values_dictionary(self._global_var_dict, raw_tool_output, prefixes) + def process_run_line(self, function_re, scrubber, raw_tool_output, prefixes): + build_global_values_dictionary( + self._global_var_dict, raw_tool_output, prefixes, self._ginfo + ) for m in function_re.finditer(raw_tool_output): if not m: continue @@ -817,7 +825,7 @@ class FunctionTestBuilder: # beginning of assembly function definition. In most assemblies, that is just a # colon: `foo:`. But, for example, in nvptx it is a brace: `foo(`. If is_backend is # False, just assume that separator is an empty string. - if is_backend: + if self._ginfo.is_asm(): # Use ':' as default separator. func_name_separator = ( m.group("func_name_separator") @@ -900,7 +908,6 @@ class FunctionTestBuilder: funcdef_attrs_and_ret, args_and_sig, attrs, - is_backend, ): self._func_dict[prefix][func].scrub = scrubbed_extra self._func_dict[prefix][func].args_and_sig = args_and_sig @@ -919,6 +926,7 @@ class FunctionTestBuilder: args_and_sig, attrs, func_name_separator, + self._ginfo, ) self._func_order[prefix].append(func) else: @@ -959,6 +967,12 @@ SCRUB_IR_COMMENT_RE = re.compile(r"\s*;.*") class NamelessValue: + """ + A NamelessValue object represents a type of value in the IR whose "name" we + generalize in the generated check lines; where the "name" could be an actual + name (as in e.g. `@some_global` or `%x`) or just a number (as in e.g. `%12` + or `!4`). + """ def __init__( self, check_prefix, @@ -971,12 +985,14 @@ class NamelessValue: is_number=False, replace_number_with_counter=False, match_literally=False, - interlaced_with_previous=False + interlaced_with_previous=False, + ir_suffix=r"", ): self.check_prefix = check_prefix self.check_key = check_key self.ir_prefix = ir_prefix self.ir_regexp = ir_regexp + self.ir_suffix = ir_suffix self.global_ir_rhs_regexp = global_ir_rhs_regexp self.is_before_functions = is_before_functions self.is_number = is_number @@ -987,15 +1003,10 @@ class NamelessValue: self.interlaced_with_previous = interlaced_with_previous self.variable_mapping = {} - # Return true if this kind of IR value is "local", basically if it matches '%{{.*}}'. + # Return true if this kind of IR value is defined "locally" to functions, + # which we assume is only the case precisely for LLVM IR local values. def is_local_def_ir_value(self): - return self.ir_prefix == "%" - - # Return the IR prefix and check prefix we use for this kind or IR value, - # e.g., (%, TMP) for locals. If the IR prefix is a regex, return the prefix - # used in the IR output - def get_ir_prefix_from_ir_value_match(self, match): - return re.search(self.ir_prefix, match[0])[0], self.check_prefix + return self.check_key == "%" # Return the IR regexp we use for this kind or IR value, e.g., [\w.-]+? for locals def get_ir_regex(self): @@ -1030,205 +1041,216 @@ class NamelessValue: var = var.replace("-", "_") return var.upper() - # Create a FileCheck variable from regex. - def get_value_definition(self, var, match): - # for backwards compatibility we check locals with '.*' - varname = self.get_value_name(var, self.check_prefix) - prefix = self.get_ir_prefix_from_ir_value_match(match)[0] - if self.is_number: - regex = "" # always capture a number in the default format - capture_start = "[[#" - else: - regex = self.get_ir_regex() - capture_start = "[[" - if self.is_local_def_ir_value(): - return capture_start + varname + ":" + prefix + regex + "]]" - return prefix + capture_start + varname + ":" + regex + "]]" - - # Use a FileCheck variable. - def get_value_use(self, var, match, var_prefix=None): - if var_prefix is None: - var_prefix = self.check_prefix - capture_start = "[[#" if self.is_number else "[[" - if self.is_local_def_ir_value(): - return capture_start + self.get_value_name(var, var_prefix) + "]]" - prefix = self.get_ir_prefix_from_ir_value_match(match)[0] - return prefix + capture_start + self.get_value_name(var, var_prefix) + "]]" - - -# Description of the different "unnamed" values we match in the IR, e.g., -# (local) ssa values, (debug) metadata, etc. -ir_nameless_values = [ - # check_prefix check_key ir_prefix ir_regexp global_ir_rhs_regexp - NamelessValue(r"TMP", "%", r"%", r"[\w$.-]+?", None), - NamelessValue(r"ATTR", "#", r"#", r"[0-9]+", None), - NamelessValue(r"ATTR", "#", r"attributes #", r"[0-9]+", r"{[^}]*}"), - NamelessValue(r"GLOB", "@", r"@", r"[0-9]+", None), - NamelessValue(r"GLOB", "@", r"@", r"[0-9]+", r".+", is_before_functions=True), - NamelessValue( - r"GLOBNAMED", - "@", - r"@", - r"[a-zA-Z0-9_$\"\\.-]*[a-zA-Z_$\"\\.-][a-zA-Z0-9_$\"\\.-]*", - r".+", - is_before_functions=True, - match_literally=True, - interlaced_with_previous=True, - ), - NamelessValue(r"DBG", "!", r"!dbg ", r"![0-9]+", None), - NamelessValue(r"DIASSIGNID", "!", r"!DIAssignID ", r"![0-9]+", None), - NamelessValue(r"PROF", "!", r"!prof ", r"![0-9]+", None), - NamelessValue(r"TBAA", "!", r"!tbaa ", r"![0-9]+", None), - NamelessValue(r"TBAA_STRUCT", "!", r"!tbaa.struct ", r"![0-9]+", None), - NamelessValue(r"RNG", "!", r"!range ", r"![0-9]+", None), - NamelessValue(r"LOOP", "!", r"!llvm.loop ", r"![0-9]+", None), - NamelessValue(r"META", "!", r"", r"![0-9]+", r"(?:distinct |)!.*"), - NamelessValue(r"ACC_GRP", "!", r"!llvm.access.group ", r"![0-9]+", None), - NamelessValue(r"META", "!", r"![a-z.]+ ", r"![0-9]+", None), - NamelessValue(r"META", "!", r"[, (]", r"![0-9]+", None), -] + def get_affixes_from_match(self, match: re.Match): + prefix = re.match(self.ir_prefix, match.group(2)).group(0) + suffix = re.search(self.ir_suffix + "$", match.group(2)).group(0) + return prefix, suffix -global_nameless_values = [ - nameless_value - for nameless_value in ir_nameless_values - if nameless_value.global_ir_rhs_regexp is not None -] -# global variable names should be matched literally -global_nameless_values_w_unstable_ids = [ - nameless_value - for nameless_value in global_nameless_values - if not nameless_value.match_literally -] -asm_nameless_values = [ - NamelessValue( - r"MCINST", - "Inst#", - "\s]|\Z)" -ASM_VALUE_RE = re.compile( - r"((?:#|//)\s*)" + "(" + ASM_VALUE_REGEXP_STRING + ")" + ASM_VALUE_REGEXP_SUFFIX -) + return ( + re.compile( + self._regexp_prefix + r"(" + regexp_string + r")" + self._regexp_suffix + ), + values, + ) -ANALYZE_VALUE_REGEXP_PREFIX = r"(\s*)" -ANALYZE_VALUE_REGEXP_STRING = r"" -for nameless_value in analyze_nameless_values: - match = createPrefixMatch(nameless_value.ir_prefix, nameless_value.ir_regexp) - ANALYZE_VALUE_REGEXP_STRING = createOrRegexp(ANALYZE_VALUE_REGEXP_STRING, match) -ANALYZE_VALUE_REGEXP_SUFFIX = r"(\)?:)" -ANALYZE_VALUE_RE = re.compile( - ANALYZE_VALUE_REGEXP_PREFIX - + r"(" - + ANALYZE_VALUE_REGEXP_STRING - + r")" - + ANALYZE_VALUE_REGEXP_SUFFIX -) + def get_version(self): + return self._version -# The entire match is group 0, the prefix has one group (=1), the entire -# IR_VALUE_REGEXP_STRING is one group (=2), and then the nameless values start. -first_nameless_group_in_ir_value_match = 3 + def is_ir(self): + return self._mode == GeneralizerInfo.MODE_IR -# constants for the group id of special matches -variable_group_in_ir_value_match = 3 -attribute_group_in_ir_value_match = 4 + def is_asm(self): + return self._mode == GeneralizerInfo.MODE_ASM + def is_analyze(self): + return self._mode == GeneralizerInfo.MODE_ANALYZE -# Check a match for IR_VALUE_RE and inspect it to determine if it was a local -# value, %..., global @..., debug number !dbg !..., etc. See the PREFIXES above. -def get_idx_from_ir_value_match(match): - for i in range(first_nameless_group_in_ir_value_match, match.lastindex): - if match.group(i) is not None: - return i - first_nameless_group_in_ir_value_match - error("Unable to identify the kind of IR value from the match!") - return 0 + def get_nameless_values(self): + return self._nameless_values + def get_regexp(self): + return self._regexp -# See get_idx_from_ir_value_match -def get_name_from_ir_value_match(match): - return match.group( - get_idx_from_ir_value_match(match) + first_nameless_group_in_ir_value_match - ) + def get_unstable_globals_regexp(self): + return self._unstable_globals_regexp + # The entire match is group 0, the prefix has one group (=1), the entire + # IR_VALUE_REGEXP_STRING is one group (=2), and then the nameless values start. + FIRST_NAMELESS_GROUP_IN_MATCH = 3 -def get_nameless_value_from_match(match, nameless_values) -> NamelessValue: - return nameless_values[get_idx_from_ir_value_match(match)] + def get_match_info(self, match): + """ + Returns (name, nameless_value) for the given match object + """ + if match.re == self._regexp: + values = self._nameless_values + else: + match.re == self._unstable_globals_regexp + values = self._unstable_globals_values + for i in range(len(values)): + g = match.group(i + GeneralizerInfo.FIRST_NAMELESS_GROUP_IN_MATCH) + if g is not None: + return g, values[i] + error("Unable to identify the kind of IR value from the match!") + return None, None + + # See get_idx_from_match + def get_name_from_match(self, match): + return self.get_match_info(match)[0] + + def get_nameless_value_from_match(self, match) -> NamelessValue: + return self.get_match_info(match)[1] + + +def make_ir_generalizer(version): + values = [] + + if version >= 5: + values += [ + NamelessValue(r"BB", "%", r"label %", r"[\w$.-]+?", None), + NamelessValue(r"BB", "%", r"^", r"[\w$.-]+?", None, ir_suffix=r":"), + ] + + values += [ + # check_prefix check_key ir_prefix ir_regexp global_ir_rhs_regexp + NamelessValue(r"TMP", "%", r"%", r"[\w$.-]+?", None), + NamelessValue(r"ATTR", "#", r"#", r"[0-9]+", None), + NamelessValue(r"ATTR", "#", r"attributes #", r"[0-9]+", r"{[^}]*}"), + NamelessValue(r"GLOB", "@", r"@", r"[0-9]+", None), + NamelessValue(r"GLOB", "@", r"@", r"[0-9]+", r".+", is_before_functions=True), + NamelessValue( + r"GLOBNAMED", + "@", + r"@", + r"[a-zA-Z0-9_$\"\\.-]*[a-zA-Z_$\"\\.-][a-zA-Z0-9_$\"\\.-]*", + r".+", + is_before_functions=True, + match_literally=True, + interlaced_with_previous=True, + ), + NamelessValue(r"DBG", "!", r"!dbg ", r"![0-9]+", None), + NamelessValue(r"DIASSIGNID", "!", r"!DIAssignID ", r"![0-9]+", None), + NamelessValue(r"PROF", "!", r"!prof ", r"![0-9]+", None), + NamelessValue(r"TBAA", "!", r"!tbaa ", r"![0-9]+", None), + NamelessValue(r"TBAA_STRUCT", "!", r"!tbaa.struct ", r"![0-9]+", None), + NamelessValue(r"RNG", "!", r"!range ", r"![0-9]+", None), + NamelessValue(r"LOOP", "!", r"!llvm.loop ", r"![0-9]+", None), + NamelessValue(r"META", "!", r"", r"![0-9]+", r"(?:distinct |)!.*"), + NamelessValue(r"ACC_GRP", "!", r"!llvm.access.group ", r"![0-9]+", None), + NamelessValue(r"META", "!", r"![a-z.]+ ", r"![0-9]+", None), + NamelessValue(r"META", "!", r"[, (]", r"![0-9]+", None), + ] + + prefix = r"(\s*)" + suffix = r"([,\s\(\)\}]|\Z)" + + # values = [ + # nameless_value + # for nameless_value in IR_NAMELESS_VALUES + # if not (globals_only and nameless_value.global_ir_rhs_regexp is None) and + # not (unstable_ids_only and nameless_value.match_literally) + # ] + + return GeneralizerInfo(version, GeneralizerInfo.MODE_IR, values, prefix, suffix) + + +def make_asm_generalizer(version): + values = [ + NamelessValue( + r"MCINST", + "Inst#", + "\s]|\Z)" + + return GeneralizerInfo(version, GeneralizerInfo.MODE_ASM, values, prefix, suffix) + + +def make_analyze_generalizer(version): + values = [ + NamelessValue( + r"GRP", + "#", + r"", + r"0x[0-9a-f]+", + None, + replace_number_with_counter=True, + ), + ] + + prefix = r"(\s*)" + suffix = r"(\)?:)" + + return GeneralizerInfo( + version, GeneralizerInfo.MODE_ANALYZE, values, prefix, suffix + ) # Return true if var clashes with the scripted FileCheck check_prefix. @@ -1385,16 +1407,68 @@ METAVAR_RE = re.compile(r"\[\[([A-Z0-9_]+)(?::[^]]+)?\]\]") NUMERIC_SUFFIX_RE = re.compile(r"[0-9]*$") +class TestVar: + def __init__(self, nameless_value: NamelessValue, prefix: str, suffix: str): + self._nameless_value = nameless_value + + self._prefix = prefix + self._suffix = suffix + + def seen(self, nameless_value: NamelessValue, prefix: str, suffix: str): + if prefix != self._prefix: + self._prefix = "" + if suffix != self._suffix: + self._suffix = "" + + def get_variable_name(self, text): + return self._nameless_value.get_value_name( + text, self._nameless_value.check_prefix + ) + + def get_def(self, name, prefix, suffix): + if self._nameless_value.is_number: + return f"{prefix}[[#{name}:]]{suffix}" + if self._prefix: + assert self._prefix == prefix + prefix = "" + if self._suffix: + assert self._suffix == suffix + suffix = "" + return f"{prefix}[[{name}:{self._prefix}{self._nameless_value.get_ir_regex()}{self._suffix}]]{suffix}" + + def get_use(self, name, prefix, suffix): + if self._nameless_value.is_number: + return f"{prefix}[[#{name}]]{suffix}" + if self._prefix: + assert self._prefix == prefix + prefix = "" + if self._suffix: + assert self._suffix == suffix + suffix = "" + return f"{prefix}[[{name}]]{suffix}" + + class CheckValueInfo: def __init__( self, - nameless_value: NamelessValue, - var: str, + key, + text, + name: str, prefix: str, + suffix: str, ): - self.nameless_value = nameless_value - self.var = var + # Key for the value, e.g. '%' + self.key = key + + # Text to be matched by the FileCheck variable (without any prefix or suffix) + self.text = text + + # Name of the FileCheck variable + self.name = name + + # Prefix and suffix that were captured by the NamelessValue regular expression self.prefix = prefix + self.suffix = suffix # Represent a check line in a way that allows us to compare check lines while @@ -1433,7 +1507,7 @@ def remap_metavar_names( new_mapping = {} for line in new_line_infos: for value in line.values: - new_mapping[value.var] = value.var + new_mapping[value.name] = value.name # Recursively commit to the identity mapping or find a better one def recurse(old_begin, old_end, new_begin, new_end): @@ -1445,7 +1519,7 @@ def remap_metavar_names( def diffify_line(line, mapper): values = [] for value in line.values: - mapped = mapper(value.var) + mapped = mapper(value.name) values.append(mapped if mapped in committed_names else "?") return line.line.strip() + " @@@ " + " @ ".join(values) @@ -1470,29 +1544,29 @@ def remap_metavar_names( local_commits = {} for lhs_value, rhs_value in zip(lhs_line.values, rhs_line.values): - if new_mapping[rhs_value.var] in committed_names: + if new_mapping[rhs_value.name] in committed_names: # The new value has already been committed. If it was mapped # to the same name as the original value, we can consider # committing other values from this line. Otherwise, we # should ignore this line. - if new_mapping[rhs_value.var] == lhs_value.var: + if new_mapping[rhs_value.name] == lhs_value.name: continue else: break - if rhs_value.var in local_commits: + if rhs_value.name in local_commits: # Same, but for a possible commit happening on the same line - if local_commits[rhs_value.var] == lhs_value.var: + if local_commits[rhs_value.name] == lhs_value.name: continue else: break - if lhs_value.var in committed_names: + if lhs_value.name in committed_names: # We can't map this value because the name we would map it to has already been # committed for something else. Give up on this line. break - local_commits[rhs_value.var] = lhs_value.var + local_commits[rhs_value.name] = lhs_value.name else: # No reason not to add any commitments for this line for rhs_var, lhs_var in local_commits.items(): @@ -1545,58 +1619,26 @@ def remap_metavar_names( return new_mapping -def generalize_check_lines_common( +def generalize_check_lines( lines, - is_analyze, + ginfo: GeneralizerInfo, vars_seen, global_vars_seen, - nameless_values, - nameless_value_regex, - is_asm, - preserve_names, + preserve_names=False, original_check_lines=None, + *, + unstable_globals_only=False, ): - # This gets called for each match that occurs in - # a line. We transform variables we haven't seen - # into defs, and variables we have seen into uses. - def transform_line_vars(match, transform_locals=True): - var = get_name_from_ir_value_match(match) - nameless_value = get_nameless_value_from_match(match, nameless_values) - if may_clash_with_default_check_prefix_name(nameless_value.check_prefix, var): - warn( - "Change IR value name '%s' or use --prefix-filecheck-ir-name to prevent possible conflict" - " with scripted FileCheck name." % (var,) - ) - key = (var, nameless_value.check_key) - is_local_def = nameless_value.is_local_def_ir_value() - if is_local_def and not transform_locals: - return None - if is_local_def and key in vars_seen: - rv = nameless_value.get_value_use(var, match) - elif not is_local_def and key in global_vars_seen: - # We could have seen a different prefix for the global variables first, - # ensure we use that one instead of the prefix for the current match. - rv = nameless_value.get_value_use(var, match, global_vars_seen[key]) - else: - if is_local_def: - vars_seen.add(key) - else: - global_vars_seen[key] = nameless_value.check_prefix - rv = nameless_value.get_value_definition(var, match) - # re.sub replaces the entire regex match - # with whatever you return, so we have - # to make sure to hand it back everything - # including the commas and spaces. - return match.group(1) + rv + match.group(match.lastindex) - - def transform_non_local_line_vars(match): - return transform_line_vars(match, False) + if unstable_globals_only: + regexp = ginfo.get_unstable_globals_regexp() + else: + regexp = ginfo.get_regexp() multiple_braces_re = re.compile(r"({{+)|(}}+)") def escape_braces(match_obj): return '{{' + re.escape(match_obj.group(0)) + '}}' - if not is_asm and not is_analyze: + if ginfo.is_ir(): for i, line in enumerate(lines): # An IR variable named '%.' matches the FileCheck regex string. line = line.replace("%.", "%dot") @@ -1617,123 +1659,141 @@ def generalize_check_lines_common( lines[i] = scrubbed_line if not preserve_names: - if is_asm: - for i, _ in enumerate(lines): - # It can happen that two matches are back-to-back and for some reason sub - # will not replace both of them. For now we work around this by - # substituting until there is no more match. - changed = True - while changed: - (lines[i], changed) = nameless_value_regex.subn( - transform_line_vars, lines[i], count=1 - ) - else: - # LLVM IR case. Start by handling global meta variables (global IR variables, - # metadata, attributes) - for i, _ in enumerate(lines): - start = 0 - while True: - m = nameless_value_regex.search(lines[i][start:]) - if m is None: - break - start += m.start() - sub = transform_non_local_line_vars(m) - if sub is not None: - lines[i] = ( - lines[i][:start] + sub + lines[i][start + len(m.group(0)) :] - ) - start += 1 - - # Collect information about new check lines and original check lines (if any) - new_line_infos = [] - for line in lines: - filtered_line = "" - values = [] - while True: - m = nameless_value_regex.search(line) - if m is None: - filtered_line += line - break + committed_names = set( + test_var.get_variable_name(name) + for (name, _), test_var in vars_seen.items() + ) + defs = set() - var = get_name_from_ir_value_match(m) - nameless_value = get_nameless_value_from_match(m, nameless_values) - var = nameless_value.get_value_name( - var, nameless_value.check_prefix - ) + # Collect information about new check lines, and generalize global reference + new_line_infos = [] + for line in lines: + filtered_line = "" + values = [] + while True: + m = regexp.search(line) + if m is None: + filtered_line += line + break - # Replace with a [[@@]] tag, but be sure to keep the spaces and commas. - filtered_line += ( - line[: m.start()] - + m.group(1) - + VARIABLE_TAG - + m.group(m.lastindex) + name = ginfo.get_name_from_match(m) + nameless_value = ginfo.get_nameless_value_from_match(m) + prefix, suffix = nameless_value.get_affixes_from_match(m) + if may_clash_with_default_check_prefix_name( + nameless_value.check_prefix, name + ): + warn( + "Change IR value name '%s' or use --prefix-filecheck-ir-name to prevent possible conflict" + " with scripted FileCheck name." % (name,) ) - line = line[m.end() :] - values.append( - CheckValueInfo( - nameless_value=nameless_value, - var=var, - prefix=nameless_value.get_ir_prefix_from_ir_value_match(m)[ - 0 - ], - ) + + # Record the variable as seen and (for locals) accumulate + # prefixes/suffixes + is_local_def = nameless_value.is_local_def_ir_value() + if is_local_def: + vars_dict = vars_seen + else: + vars_dict = global_vars_seen + + key = (name, nameless_value.check_key) + + if is_local_def: + test_prefix = prefix + test_suffix = suffix + else: + test_prefix = "" + test_suffix = "" + + if key in vars_dict: + vars_dict[key].seen(nameless_value, test_prefix, test_suffix) + else: + vars_dict[key] = TestVar(nameless_value, test_prefix, test_suffix) + defs.add(key) + + var = vars_dict[key].get_variable_name(name) + + # Replace with a [[@@]] tag, but be sure to keep the spaces and commas. + filtered_line += ( + line[: m.start()] + m.group(1) + VARIABLE_TAG + m.group(m.lastindex) + ) + line = line[m.end() :] + + values.append( + CheckValueInfo( + key=nameless_value.check_key, + text=name, + name=var, + prefix=prefix, + suffix=suffix, ) - new_line_infos.append(CheckLineInfo(filtered_line, values)) - - orig_line_infos = [] - for line in original_check_lines or []: - filtered_line = "" - values = [] - while True: - m = METAVAR_RE.search(line) - if m is None: - filtered_line += line - break + ) - # Replace with a [[@@]] tag, but be sure to keep the spaces and commas. - filtered_line += line[: m.start()] + VARIABLE_TAG - line = line[m.end() :] - values.append( - CheckValueInfo( - nameless_value=None, - var=m.group(1), - prefix=None, - ) + new_line_infos.append(CheckLineInfo(filtered_line, values)) + + committed_names.update( + test_var.get_variable_name(name) + for (name, _), test_var in global_vars_seen.items() + ) + + # Collect information about original check lines, if any. + orig_line_infos = [] + for line in original_check_lines or []: + filtered_line = "" + values = [] + while True: + m = METAVAR_RE.search(line) + if m is None: + filtered_line += line + break + + # Replace with a [[@@]] tag, but be sure to keep the spaces and commas. + filtered_line += line[: m.start()] + VARIABLE_TAG + line = line[m.end() :] + values.append( + CheckValueInfo( + key=None, + text=None, + name=m.group(1), + prefix="", + suffix="", ) - orig_line_infos.append(CheckLineInfo(filtered_line, values)) + ) + orig_line_infos.append(CheckLineInfo(filtered_line, values)) - # Compute the variable name mapping - committed_names = set(vars_seen) + # Compute the variable name mapping + mapping = remap_metavar_names(orig_line_infos, new_line_infos, committed_names) - mapping = remap_metavar_names( - orig_line_infos, new_line_infos, committed_names - ) + # Apply the variable name mapping + for i, line_info in enumerate(new_line_infos): + line_template = line_info.line + line = "" - for i, line_info in enumerate(new_line_infos): - line_template = line_info.line - line = "" + for value in line_info.values: + idx = line_template.find(VARIABLE_TAG) + line += line_template[:idx] + line_template = line_template[idx + len(VARIABLE_TAG) :] - for value in line_info.values: - idx = line_template.find(VARIABLE_TAG) - line += line_template[:idx] - line_template = line_template[idx + len(VARIABLE_TAG) :] + key = (value.text, value.key) + if value.key == "%": + vars_dict = vars_seen + else: + vars_dict = global_vars_seen - key = (mapping[value.var], nameless_value.check_key) - is_local_def = nameless_value.is_local_def_ir_value() - if is_local_def: - if mapping[value.var] in vars_seen: - line += f"[[{mapping[value.var]}]]" - else: - line += f"[[{mapping[value.var]}:{value.prefix}{value.nameless_value.get_ir_regex()}]]" - vars_seen.add(mapping[value.var]) - else: - raise RuntimeError("not implemented") + if key in defs: + line += vars_dict[key].get_def( + mapping[value.name], value.prefix, value.suffix + ) + defs.remove(key) + else: + line += vars_dict[key].get_use( + mapping[value.name], value.prefix, value.suffix + ) - line += line_template + line += line_template - lines[i] = line + lines[i] = line - if is_analyze: + if ginfo.is_analyze(): for i, _ in enumerate(lines): # Escape multiple {{ or }} as {{}} denotes a FileCheck regex. scrubbed_line = multiple_braces_re.sub(escape_braces, lines[i]) @@ -1742,63 +1802,6 @@ def generalize_check_lines_common( return lines -# Replace IR value defs and uses with FileCheck variables. -def generalize_check_lines( - lines, is_analyze, vars_seen, global_vars_seen, preserve_names, original_check_lines -): - return generalize_check_lines_common( - lines, - is_analyze, - vars_seen, - global_vars_seen, - ir_nameless_values, - IR_VALUE_RE, - False, - preserve_names, - original_check_lines=original_check_lines, - ) - - -def generalize_global_check_line(line, preserve_names, global_vars_seen): - [new_line] = generalize_check_lines_common( - [line], - False, - set(), - global_vars_seen, - global_nameless_values_w_unstable_ids, - GLOBAL_VALUE_RE, - False, - preserve_names, - ) - return new_line - - -def generalize_asm_check_lines(lines, vars_seen, global_vars_seen): - return generalize_check_lines_common( - lines, - False, - vars_seen, - global_vars_seen, - asm_nameless_values, - ASM_VALUE_RE, - True, - False, - ) - - -def generalize_analyze_check_lines(lines, vars_seen, global_vars_seen): - return generalize_check_lines_common( - lines, - True, - vars_seen, - global_vars_seen, - analyze_nameless_values, - ANALYZE_VALUE_RE, - False, - False, - ) - - def add_checks( output_lines, comment_marker, @@ -1806,9 +1809,7 @@ def add_checks( func_dict, func_name, check_label_format, - is_backend, - is_analyze, - version, + ginfo, global_vars_seen_dict, is_filtered, preserve_names=False, @@ -1853,7 +1854,7 @@ def add_checks( # Add some space between different check prefixes, but not after the last # check line (before the test code). - if is_backend: + if ginfo.is_asm(): if len(printed_prefixes) != 0: output_lines.append(comment_marker) @@ -1862,11 +1863,11 @@ def add_checks( global_vars_seen_before = [key for key in global_vars_seen.keys()] - vars_seen = set() + vars_seen = {} printed_prefixes.append(checkprefix) attrs = str(func_dict[checkprefix][func_name].attrs) attrs = "" if attrs == "None" else attrs - if version > 1: + if ginfo.get_version() > 1: funcdef_attrs_and_ret = func_dict[checkprefix][ func_name ].funcdef_attrs_and_ret @@ -1881,7 +1882,7 @@ def add_checks( if args_and_sig: args_and_sig = generalize_check_lines( [args_and_sig], - is_analyze, + ginfo, vars_seen, global_vars_seen, preserve_names, @@ -1892,7 +1893,7 @@ def add_checks( # Captures in label lines are not supported, thus split into a -LABEL # and a separate -SAME line that contains the arguments with captures. args_and_sig_prefix = "" - if version >= 3 and args_and_sig.startswith("("): + if ginfo.get_version() >= 3 and args_and_sig.startswith("("): # Ensure the "(" separating function name and arguments is in the # label line. This is required in case of function names that are # prefixes of each other. Otherwise, the label line for "foo" might @@ -1933,7 +1934,7 @@ def add_checks( continue # For ASM output, just emit the check lines. - if is_backend: + if ginfo.is_asm(): body_start = 1 if is_filtered: # For filtered output we don't add "-NEXT" so don't add extra spaces @@ -1943,8 +1944,8 @@ def add_checks( output_lines.append( "%s %s: %s" % (comment_marker, checkprefix, func_body[0]) ) - func_lines = generalize_asm_check_lines( - func_body[body_start:], vars_seen, global_vars_seen + func_lines = generalize_check_lines( + func_body[body_start:], ginfo, vars_seen, global_vars_seen ) for func_line in func_lines: if func_line.strip() == "": @@ -1963,9 +1964,9 @@ def add_checks( global_vars_seen_dict[checkprefix][key] = global_vars_seen[key] break # For analyze output, generalize the output, and emit CHECK-EMPTY lines as well. - elif is_analyze: - func_body = generalize_analyze_check_lines( - func_body, vars_seen, global_vars_seen + elif ginfo.is_analyze(): + func_body = generalize_check_lines( + func_body, ginfo, vars_seen, global_vars_seen ) for func_line in func_body: if func_line.strip() == "": @@ -1994,7 +1995,7 @@ def add_checks( else: func_body = generalize_check_lines( func_body, - False, + ginfo, vars_seen, global_vars_seen, preserve_names, @@ -2057,13 +2058,14 @@ def add_ir_checks( func_name, preserve_names, function_sig, - version, + ginfo: GeneralizerInfo, global_vars_seen_dict, is_filtered, original_check_lines={}, ): + assert ginfo.is_ir() # Label format is based on IR string. - if function_sig and version > 1: + if function_sig and ginfo.get_version() > 1: function_def_regex = "define %s" elif function_sig: function_def_regex = "define {{[^@]+}}%s" @@ -2079,9 +2081,7 @@ def add_ir_checks( func_dict, func_name, check_label_format, - False, - False, - version, + ginfo, global_vars_seen_dict, is_filtered, preserve_names, @@ -2090,8 +2090,15 @@ def add_ir_checks( def add_analyze_checks( - output_lines, comment_marker, prefix_list, func_dict, func_name, is_filtered + output_lines, + comment_marker, + prefix_list, + func_dict, + func_name, + ginfo: GeneralizerInfo, + is_filtered, ): + assert ginfo.is_analyze() check_label_format = "{} %s-LABEL: '%s%s%s%s'".format(comment_marker) global_vars_seen_dict = {} return add_checks( @@ -2101,16 +2108,14 @@ def add_analyze_checks( func_dict, func_name, check_label_format, - False, - True, - 1, + ginfo, global_vars_seen_dict, is_filtered, ) -def build_global_values_dictionary(glob_val_dict, raw_tool_output, prefixes): - for nameless_value in itertools.chain(global_nameless_values, asm_nameless_values): +def build_global_values_dictionary(glob_val_dict, raw_tool_output, prefixes, ginfo): + for nameless_value in ginfo.get_nameless_values(): if nameless_value.global_ir_rhs_regexp is None: continue @@ -2225,6 +2230,7 @@ def add_global_checks( comment_marker, prefix_list, output_lines, + ginfo: GeneralizerInfo, global_vars_seen_dict, preserve_names, is_before_functions, @@ -2232,7 +2238,9 @@ def add_global_checks( ): printed_prefixes = set() output_lines_loc = {} # Allows GLOB and GLOBNAMED to be sorted correctly - for nameless_value in global_nameless_values: + for nameless_value in ginfo.get_nameless_values(): + if nameless_value.global_ir_rhs_regexp is None: + continue if nameless_value.is_before_functions != is_before_functions: continue for p in prefix_list: @@ -2274,8 +2282,13 @@ def add_global_checks( break if not matched: continue - new_line = generalize_global_check_line( - line, preserve_names, global_vars_seen + [new_line] = generalize_check_lines( + [line], + ginfo, + {}, + global_vars_seen, + preserve_names, + unstable_globals_only=True, ) new_line = filter_unstable_metadata(new_line) check_line = "%s %s: %s" % (comment_marker, checkprefix, new_line) diff --git a/llvm/utils/UpdateTestChecks/isel.py b/llvm/utils/UpdateTestChecks/isel.py index bdb68e5815a3..855bc50b09f4 100644 --- a/llvm/utils/UpdateTestChecks/isel.py +++ b/llvm/utils/UpdateTestChecks/isel.py @@ -60,6 +60,7 @@ def add_checks( prefix_list, func_dict, func_name, + ginfo: common.GeneralizerInfo, global_vars_seen_dict, is_filtered, ): @@ -72,9 +73,7 @@ def add_checks( func_dict, func_name, check_label_format, - True, - False, - 1, + ginfo, global_vars_seen_dict, is_filtered=is_filtered, ) diff --git a/llvm/utils/update_analyze_test_checks.py b/llvm/utils/update_analyze_test_checks.py index 03053e5447d1..47506626a0a5 100755 --- a/llvm/utils/update_analyze_test_checks.py +++ b/llvm/utils/update_analyze_test_checks.py @@ -96,6 +96,7 @@ def main(): # now, we just ignore all but the last. prefix_list.append((check_prefixes, tool_cmd_args)) + ginfo = common.make_analyze_generalizer(version=1) builder = common.FunctionTestBuilder( run_list=prefix_list, flags=type( @@ -111,6 +112,7 @@ def main(): ), scrubber_args=[], path=ti.path, + ginfo=ginfo, ) for prefixes, opt_args in prefix_list: @@ -131,7 +133,6 @@ def main(): common.scrub_body, raw_tool_output, prefixes, - False, ) elif re.search(r"LV: Checking a loop in ", raw_tool_outputs) is not None: # Split analysis outputs by "Printing analysis " declarations. @@ -143,7 +144,6 @@ def main(): common.scrub_body, raw_tool_output, prefixes, - False, ) else: common.warn("Don't know how to deal with this output") @@ -179,6 +179,7 @@ def main(): prefix_list, func_dict, func_name, + ginfo, is_filtered=builder.is_filtered(), ) ) diff --git a/llvm/utils/update_cc_test_checks.py b/llvm/utils/update_cc_test_checks.py index 28c6bb0409f3..3ffb07ddf6ad 100755 --- a/llvm/utils/update_cc_test_checks.py +++ b/llvm/utils/update_cc_test_checks.py @@ -270,7 +270,7 @@ def get_function_body(builder, args, filename, clang_args, extra_commands, prefi raw_tool_output = common.invoke_tool(extra_args[0], extra_args[1:], f.name) if "-emit-llvm" in clang_args: builder.process_run_line( - common.OPT_FUNCTION_RE, common.scrub_body, raw_tool_output, prefixes, False + common.OPT_FUNCTION_RE, common.scrub_body, raw_tool_output, prefixes ) builder.processed_prefixes(prefixes) else: @@ -360,8 +360,13 @@ def main(): # Store only filechecked runlines. filecheck_run_list = [i for i in run_list if i[0]] + ginfo = common.make_ir_generalizer(version=ti.args.version) builder = common.FunctionTestBuilder( - run_list=filecheck_run_list, flags=ti.args, scrubber_args=[], path=ti.path + run_list=filecheck_run_list, + flags=ti.args, + scrubber_args=[], + path=ti.path, + ginfo=ginfo, ) for prefixes, args, extra_commands, triple_in_cmd in run_list: @@ -415,29 +420,18 @@ def main(): # Now generate all the checks. def check_generator(my_output_lines, prefixes, func): - if "-emit-llvm" in clang_args: - return common.add_ir_checks( - my_output_lines, - "//", - prefixes, - func_dict, - func, - False, - ti.args.function_signature, - ti.args.version, - global_vars_seen_dict, - is_filtered=builder.is_filtered(), - ) - else: - return asm.add_checks( - my_output_lines, - "//", - prefixes, - func_dict, - func, - global_vars_seen_dict, - is_filtered=builder.is_filtered(), - ) + return common.add_ir_checks( + my_output_lines, + "//", + prefixes, + func_dict, + func, + False, + ti.args.function_signature, + ginfo, + global_vars_seen_dict, + is_filtered=builder.is_filtered(), + ) if ti.args.check_globals != 'none': generated_prefixes.extend( @@ -446,6 +440,7 @@ def main(): "//", run_list, output_lines, + ginfo, global_vars_seen_dict, False, True, @@ -506,6 +501,7 @@ def main(): "//", run_list, output_lines, + ginfo, global_vars_seen_dict, False, True, @@ -525,7 +521,7 @@ def main(): mangled, False, args.function_signature, - args.version, + ginfo, global_vars_seen_dict, is_filtered=builder.is_filtered(), ) @@ -543,6 +539,7 @@ def main(): "//", run_list, output_lines, + ginfo, global_vars_seen_dict, False, False, diff --git a/llvm/utils/update_llc_test_checks.py b/llvm/utils/update_llc_test_checks.py index 1ed0132781e2..c8598e74a134 100755 --- a/llvm/utils/update_llc_test_checks.py +++ b/llvm/utils/update_llc_test_checks.py @@ -133,6 +133,7 @@ def main(): else: check_indent = "" + ginfo = common.make_asm_generalizer(version=1) builder = common.FunctionTestBuilder( run_list=run_list, flags=type( @@ -148,6 +149,7 @@ def main(): ), scrubber_args=[ti.args], path=ti.path, + ginfo=ginfo, ) for ( @@ -173,9 +175,7 @@ def main(): triple = common.get_triple_from_march(march_in_cmd) scrubber, function_re = output_type.get_run_handler(triple) - builder.process_run_line( - function_re, scrubber, raw_tool_output, prefixes, True - ) + builder.process_run_line(function_re, scrubber, raw_tool_output, prefixes) builder.processed_prefixes(prefixes) func_dict = builder.finish_and_get_func_dict() @@ -218,6 +218,7 @@ def main(): prefixes, func_dict, func, + ginfo, global_vars_seen_dict, is_filtered=builder.is_filtered(), ), @@ -243,6 +244,7 @@ def main(): run_list, func_dict, func_name, + ginfo, global_vars_seen_dict, is_filtered=builder.is_filtered(), ) diff --git a/llvm/utils/update_test_checks.py b/llvm/utils/update_test_checks.py index 04808ce6bb1c..16f3e618770b 100755 --- a/llvm/utils/update_test_checks.py +++ b/llvm/utils/update_test_checks.py @@ -147,9 +147,14 @@ def main(): # now, we just ignore all but the last. prefix_list.append((check_prefixes, tool_cmd_args, preprocess_cmd)) + ginfo = common.make_ir_generalizer(ti.args.version) global_vars_seen_dict = {} builder = common.FunctionTestBuilder( - run_list=prefix_list, flags=ti.args, scrubber_args=[], path=ti.path + run_list=prefix_list, + flags=ti.args, + scrubber_args=[], + path=ti.path, + ginfo=ginfo, ) tool_binary = ti.args.tool_binary @@ -172,7 +177,6 @@ def main(): common.scrub_body, raw_tool_output, prefixes, - False, ) builder.processed_prefixes(prefixes) @@ -217,6 +221,7 @@ def main(): ";", prefix_list, output_lines, + ginfo, global_vars_seen_dict, args.preserve_names, True, @@ -239,7 +244,7 @@ def main(): func, False, args.function_signature, - args.version, + ginfo, global_vars_seen_dict, is_filtered=builder.is_filtered(), original_check_lines=original_check_lines.get(func, {}), @@ -271,7 +276,7 @@ def main(): func_name, args.preserve_names, args.function_signature, - args.version, + ginfo, global_vars_seen_dict, is_filtered=builder.is_filtered(), original_check_lines=original_check_lines.get( @@ -290,6 +295,7 @@ def main(): ";", prefix_list, output_lines, + ginfo, global_vars_seen_dict, args.preserve_names, True, @@ -337,6 +343,7 @@ def main(): ";", prefix_list, output_lines, + ginfo, global_vars_seen_dict, args.preserve_names, False, -- GitLab From d34be649af1aa849c21a5a0570617c3a89d5f0b8 Mon Sep 17 00:00:00 2001 From: Mingming Liu Date: Sat, 18 May 2024 19:39:57 -0700 Subject: [PATCH 009/793] [ThinLTO]Sort imported GUIDs before cache key update (#92622) Add 'sort' here since it's helpful when container type changes (for example, https://github.com/llvm/llvm-project/pull/88024 wants to change container type from `unordered_set` to `DenseMap) @MaskRay points out `std::` doesn't randomize the iteration order of `unordered_{set,map}`, and the iteration order for single build is deterministic. --- llvm/lib/LTO/LTO.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index 21cad1de0ced..5c603ac6ab47 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -199,13 +199,19 @@ void llvm::computeLTOCacheKey( [](const ImportModule &Lhs, const ImportModule &Rhs) -> bool { return Lhs.getHash() < Rhs.getHash(); }); + std::vector ImportedGUIDs; for (const ImportModule &Entry : ImportModulesVector) { auto ModHash = Entry.getHash(); Hasher.update(ArrayRef((uint8_t *)&ModHash[0], sizeof(ModHash))); AddUint64(Entry.getFunctions().size()); + + ImportedGUIDs.clear(); for (auto &Fn : Entry.getFunctions()) - AddUint64(Fn); + ImportedGUIDs.push_back(Fn); + llvm::sort(ImportedGUIDs); + for (auto &GUID : ImportedGUIDs) + AddUint64(GUID); } // Include the hash for the resolved ODR. -- GitLab From 7b977e0f644c43232732e149b03d41de321d804e Mon Sep 17 00:00:00 2001 From: Mingming Liu Date: Sat, 18 May 2024 21:51:14 -0700 Subject: [PATCH 010/793] [nfc][InstrFDO]Encapsulate header writes in a class member function (#90142) The smaller class member are more focused and easier to maintain. This also paves the way for partial header forward compatibility in https://github.com/llvm/llvm-project/pull/88212 --------- Co-authored-by: Kazu Hirata --- .../llvm/ProfileData/InstrProfWriter.h | 6 ++ llvm/lib/ProfileData/InstrProfWriter.cpp | 70 +++++++++---------- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/llvm/include/llvm/ProfileData/InstrProfWriter.h b/llvm/include/llvm/ProfileData/InstrProfWriter.h index 1714f3b6cf3a..97f6a95ab715 100644 --- a/llvm/include/llvm/ProfileData/InstrProfWriter.h +++ b/llvm/include/llvm/ProfileData/InstrProfWriter.h @@ -212,6 +212,12 @@ private: void addTemporalProfileTrace(TemporalProfTraceTy Trace); Error writeImpl(ProfOStream &OS); + + // Writes known header fields and reserves space for fields whose value are + // known only after payloads are written. Returns the start byte offset for + // back patching. + uint64_t writeHeader(const IndexedInstrProf::Header &header, + const bool WritePrevVersion, ProfOStream &OS); }; } // end namespace llvm diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp index b5b13550b057..101992c38353 100644 --- a/llvm/lib/ProfileData/InstrProfWriter.cpp +++ b/llvm/lib/ProfileData/InstrProfWriter.cpp @@ -639,6 +639,27 @@ static Error writeMemProf(ProfOStream &OS, memprof::MaximumSupportedVersion)); } +uint64_t InstrProfWriter::writeHeader(const IndexedInstrProf::Header &Header, + const bool WritePrevVersion, + ProfOStream &OS) { + // Only write out the first four fields. + for (int I = 0; I < 4; I++) + OS.write(reinterpret_cast(&Header)[I]); + + // Remember the offset of the remaining fields to allow back patching later. + auto BackPatchStartOffset = OS.tell(); + + // Reserve the space for back patching later. + OS.write(0); // HashOffset + OS.write(0); // MemProfOffset + OS.write(0); // BinaryIdOffset + OS.write(0); // TemporalProfTracesOffset + if (!WritePrevVersion) + OS.write(0); // VTableNamesOffset + + return BackPatchStartOffset; +} + Error InstrProfWriter::writeImpl(ProfOStream &OS) { using namespace IndexedInstrProf; using namespace support; @@ -651,7 +672,7 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) { InfoObj->CSSummaryBuilder = &CSISB; // Populate the hash table generator. - SmallVector, 0> OrderedData; + SmallVector> OrderedData; for (const auto &I : FunctionData) if (shouldEncodeData(I.getValue())) OrderedData.emplace_back((I.getKey()), &I.getValue()); @@ -693,35 +714,8 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) { Header.TemporalProfTracesOffset = 0; Header.VTableNamesOffset = 0; - // Only write out the first four fields. We need to remember the offset of the - // remaining fields to allow back patching later. - for (int I = 0; I < 4; I++) - OS.write(reinterpret_cast(&Header)[I]); - - // Save the location of Header.HashOffset field in \c OS. - uint64_t HashTableStartFieldOffset = OS.tell(); - // Reserve the space for HashOffset field. - OS.write(0); - - // Save the location of MemProf profile data. This is stored in two parts as - // the schema and as a separate on-disk chained hashtable. - uint64_t MemProfSectionOffset = OS.tell(); - // Reserve space for the MemProf table field to be patched later if this - // profile contains memory profile information. - OS.write(0); - - // Save the location of binary ids section. - uint64_t BinaryIdSectionOffset = OS.tell(); - // Reserve space for the BinaryIdOffset field to be patched later if this - // profile contains binary ids. - OS.write(0); - - uint64_t TemporalProfTracesOffset = OS.tell(); - OS.write(0); - - uint64_t VTableNamesOffset = OS.tell(); - if (!WritePrevVersion) - OS.write(0); + const uint64_t BackPatchStartOffset = + writeHeader(Header, WritePrevVersion, OS); // Reserve space to write profile summary data. uint32_t NumEntries = ProfileSummaryBuilder::DefaultCutoffs.size(); @@ -850,16 +844,20 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) { } InfoObj->CSSummaryBuilder = nullptr; + const size_t MemProfOffset = BackPatchStartOffset + sizeof(uint64_t); + const size_t BinaryIdOffset = MemProfOffset + sizeof(uint64_t); + const size_t TemporalProfTracesOffset = BinaryIdOffset + sizeof(uint64_t); + const size_t VTableNamesOffset = TemporalProfTracesOffset + sizeof(uint64_t); if (!WritePrevVersion) { // Now do the final patch: PatchItem PatchItems[] = { // Patch the Header.HashOffset field. - {HashTableStartFieldOffset, &HashTableStart, 1}, + {BackPatchStartOffset, &HashTableStart, 1}, // Patch the Header.MemProfOffset (=0 for profiles without MemProf // data). - {MemProfSectionOffset, &MemProfSectionStart, 1}, + {MemProfOffset, &MemProfSectionStart, 1}, // Patch the Header.BinaryIdSectionOffset. - {BinaryIdSectionOffset, &BinaryIdSectionStart, 1}, + {BinaryIdOffset, &BinaryIdSectionStart, 1}, // Patch the Header.TemporalProfTracesOffset (=0 for profiles without // traces). {TemporalProfTracesOffset, &TemporalProfTracesSectionStart, 1}, @@ -875,12 +873,12 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) { // Now do the final patch: PatchItem PatchItems[] = { // Patch the Header.HashOffset field. - {HashTableStartFieldOffset, &HashTableStart, 1}, + {BackPatchStartOffset, &HashTableStart, 1}, // Patch the Header.MemProfOffset (=0 for profiles without MemProf // data). - {MemProfSectionOffset, &MemProfSectionStart, 1}, + {MemProfOffset, &MemProfSectionStart, 1}, // Patch the Header.BinaryIdSectionOffset. - {BinaryIdSectionOffset, &BinaryIdSectionStart, 1}, + {BinaryIdOffset, &BinaryIdSectionStart, 1}, // Patch the Header.TemporalProfTracesOffset (=0 for profiles without // traces). {TemporalProfTracesOffset, &TemporalProfTracesSectionStart, 1}, -- GitLab From f87ed54e495eba7b9897654de4c17fbf101cb620 Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi Date: Sun, 19 May 2024 15:37:42 +0900 Subject: [PATCH 011/793] Reformat --- compiler-rt/lib/ctx_profile/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler-rt/lib/ctx_profile/CMakeLists.txt b/compiler-rt/lib/ctx_profile/CMakeLists.txt index ab7bf3241fd6..d69cdf56df8f 100644 --- a/compiler-rt/lib/ctx_profile/CMakeLists.txt +++ b/compiler-rt/lib/ctx_profile/CMakeLists.txt @@ -26,4 +26,4 @@ add_compiler_rt_runtime(clang_rt.ctx_profile CFLAGS ${EXTRA_FLAGS} SOURCES ${CTX_PROFILE_SOURCES} ADDITIONAL_HEADERS ${CTX_PROFILE_HEADERS} - PARENT_TARGET ctx_profile) \ No newline at end of file + PARENT_TARGET ctx_profile) -- GitLab From 9d15fc0060b584141674dddfedb06b0b58ad7aae Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi Date: Sun, 19 May 2024 15:41:03 +0900 Subject: [PATCH 012/793] Quick fix for a waning in clang_rt.ctx_profile [-Wgnu-anonymous-struct] `__sanitizer_siginfo` has been introduced in D142117. (llvmorg-16-init-17950-ged9ef9b4f248) It is incompatible to -pedantic. `clang_rt.ctx_profile` has been introduced in #92456. --- compiler-rt/cmake/config-ix.cmake | 1 + compiler-rt/lib/ctx_profile/CMakeLists.txt | 3 +++ 2 files changed, 4 insertions(+) diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index ba740af9e1d6..42edbe15edaf 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -127,6 +127,7 @@ check_cxx_compiler_flag("-Werror -Wframe-larger-than=512" COMPILER_RT_HAS_WFRAME check_cxx_compiler_flag("-Werror -Wglobal-constructors" COMPILER_RT_HAS_WGLOBAL_CONSTRUCTORS_FLAG) check_cxx_compiler_flag("-Werror -Wc99-extensions" COMPILER_RT_HAS_WC99_EXTENSIONS_FLAG) check_cxx_compiler_flag("-Werror -Wgnu" COMPILER_RT_HAS_WGNU_FLAG) +check_cxx_compiler_flag("-Werror -Wgnu-anonymous-struct" COMPILER_RT_HAS_WGNU_ANONYMOUS_STRUCT_FLAG) check_cxx_compiler_flag("-Werror -Wvariadic-macros" COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG) check_cxx_compiler_flag("-Werror -Wunused-parameter" COMPILER_RT_HAS_WUNUSED_PARAMETER_FLAG) check_cxx_compiler_flag("-Werror -Wcovered-switch-default" COMPILER_RT_HAS_WCOVERED_SWITCH_DEFAULT_FLAG) diff --git a/compiler-rt/lib/ctx_profile/CMakeLists.txt b/compiler-rt/lib/ctx_profile/CMakeLists.txt index d69cdf56df8f..ce491fc7e8bf 100644 --- a/compiler-rt/lib/ctx_profile/CMakeLists.txt +++ b/compiler-rt/lib/ctx_profile/CMakeLists.txt @@ -15,6 +15,9 @@ include_directories(../../include) # We don't use the C++ Standard Library here, so avoid including it by mistake. append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ EXTRA_FLAGS) +# __sanitizer_siginfo +append_list_if(COMPILER_RT_HAS_WGNU_ANONYMOUS_STRUCT_FLAG -Wno-gnu-anonymous-struct EXTRA_FLAGS) + if(COMPILER_RT_INCLUDE_TESTS) add_subdirectory(tests) endif() -- GitLab From b4ba3fe0068b2391e24ebf9a0ec6f56a8ac224b4 Mon Sep 17 00:00:00 2001 From: paperchalice Date: Sun, 19 May 2024 15:57:02 +0800 Subject: [PATCH 013/793] [NewPM][AMDGPU] Add CodeGenPassBuilder (#91040) In order to test SelectionDAG for target AMDGPU, we need CodeGenPassBuilder. --- .../AMDGPU/AMDGPUCodeGenPassBuilder.cpp | 38 +++++++++++++++++++ .../Target/AMDGPU/AMDGPUCodeGenPassBuilder.h | 33 ++++++++++++++++ .../lib/Target/AMDGPU/AMDGPUTargetMachine.cpp | 9 +++++ llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.h | 6 +++ llvm/lib/Target/AMDGPU/CMakeLists.txt | 3 ++ .../Target/AMDGPU/R600CodeGenPassBuilder.cpp | 33 ++++++++++++++++ .../Target/AMDGPU/R600CodeGenPassBuilder.h | 32 ++++++++++++++++ llvm/lib/Target/AMDGPU/R600TargetMachine.cpp | 9 +++++ llvm/lib/Target/AMDGPU/R600TargetMachine.h | 6 +++ 9 files changed, 169 insertions(+) create mode 100644 llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.cpp create mode 100644 llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.h create mode 100644 llvm/lib/Target/AMDGPU/R600CodeGenPassBuilder.cpp create mode 100644 llvm/lib/Target/AMDGPU/R600CodeGenPassBuilder.h diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.cpp new file mode 100644 index 000000000000..01ab61a0e407 --- /dev/null +++ b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.cpp @@ -0,0 +1,38 @@ +//===- lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.cpp ---------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "AMDGPUCodeGenPassBuilder.h" +#include "AMDGPUTargetMachine.h" + +using namespace llvm; + +AMDGPUCodeGenPassBuilder::AMDGPUCodeGenPassBuilder( + AMDGPUTargetMachine &TM, const CGPassBuilderOption &Opts, + PassInstrumentationCallbacks *PIC) + : CodeGenPassBuilder(TM, Opts, PIC) { + Opt.RequiresCodeGenSCCOrder = true; + // Exceptions and StackMaps are not supported, so these passes will never do + // anything. + // Garbage collection is not supported. + disablePass(); +} + +void AMDGPUCodeGenPassBuilder::addPreISel(AddIRPass &addPass) const { + // TODO: Add passes pre instruction selection. +} + +void AMDGPUCodeGenPassBuilder::addAsmPrinter(AddMachinePass &addPass, + CreateMCStreamer) const { + // TODO: Add AsmPrinter. +} + +Error AMDGPUCodeGenPassBuilder::addInstSelector(AddMachinePass &) const { + // TODO: Add instruction selector. + return Error::success(); +} diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.h b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.h new file mode 100644 index 000000000000..5f79e309703a --- /dev/null +++ b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.h @@ -0,0 +1,33 @@ +//===- lib/Target/AMDGPU/AMDGPUCodeGenPassBuilder.h -----------*- C++ -*---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUCODEGENPASSBUILDER_H +#define LLVM_LIB_TARGET_AMDGPU_AMDGPUCODEGENPASSBUILDER_H + +#include "llvm/MC/MCStreamer.h" +#include "llvm/Passes/CodeGenPassBuilder.h" + +namespace llvm { + +class AMDGPUTargetMachine; + +class AMDGPUCodeGenPassBuilder + : public CodeGenPassBuilder { +public: + AMDGPUCodeGenPassBuilder(AMDGPUTargetMachine &TM, + const CGPassBuilderOption &Opts, + PassInstrumentationCallbacks *PIC); + + void addPreISel(AddIRPass &addPass) const; + void addAsmPrinter(AddMachinePass &, CreateMCStreamer) const; + Error addInstSelector(AddMachinePass &) const; +}; + +} // namespace llvm + +#endif // LLVM_LIB_TARGET_AMDGPU_AMDGPUCODEGENPASSBUILDER_H diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp index 305a6c8c3b92..20329dea6027 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp @@ -15,6 +15,7 @@ #include "AMDGPUTargetMachine.h" #include "AMDGPU.h" #include "AMDGPUAliasAnalysis.h" +#include "AMDGPUCodeGenPassBuilder.h" #include "AMDGPUCtorDtorLowering.h" #include "AMDGPUExportClustering.h" #include "AMDGPUIGroupLP.h" @@ -646,6 +647,14 @@ parseAMDGPUAtomicOptimizerStrategy(StringRef Params) { return make_error("invalid parameter", inconvertibleErrorCode()); } +Error AMDGPUTargetMachine::buildCodeGenPipeline( + ModulePassManager &MPM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, + CodeGenFileType FileType, const CGPassBuilderOption &Opts, + PassInstrumentationCallbacks *PIC) { + AMDGPUCodeGenPassBuilder CGPB(*this, Opts, PIC); + return CGPB.buildPipeline(MPM, Out, DwoOut, FileType); +} + void AMDGPUTargetMachine::registerPassBuilderCallbacks( PassBuilder &PB, bool PopulateClassToPassNames) { diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.h b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.h index 30ab388c7d52..e48cb8fdc657 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.h @@ -52,6 +52,12 @@ public: return TLOF.get(); } + Error buildCodeGenPipeline(ModulePassManager &MPM, raw_pwrite_stream &Out, + raw_pwrite_stream *DwoOut, + CodeGenFileType FileType, + const CGPassBuilderOption &Opts, + PassInstrumentationCallbacks *PIC) override; + void registerPassBuilderCallbacks(PassBuilder &PB, bool PopulateClassToPassNames) override; void registerDefaultAliasAnalyses(AAManager &) override; diff --git a/llvm/lib/Target/AMDGPU/CMakeLists.txt b/llvm/lib/Target/AMDGPU/CMakeLists.txt index 48325a0928f9..ead81b402eb7 100644 --- a/llvm/lib/Target/AMDGPU/CMakeLists.txt +++ b/llvm/lib/Target/AMDGPU/CMakeLists.txt @@ -50,6 +50,7 @@ add_llvm_target(AMDGPUCodeGen AMDGPUAtomicOptimizer.cpp AMDGPUAttributor.cpp AMDGPUCallLowering.cpp + AMDGPUCodeGenPassBuilder.cpp AMDGPUCodeGenPrepare.cpp AMDGPUCombinerHelper.cpp AMDGPUCtorDtorLowering.cpp @@ -119,6 +120,7 @@ add_llvm_target(AMDGPUCodeGen GCNVOPDUtils.cpp R600AsmPrinter.cpp R600ClauseMergePass.cpp + R600CodeGenPassBuilder.cpp R600ControlFlowFinalizer.cpp R600EmitClauseMarkers.cpp R600ExpandSpecialInstrs.cpp @@ -182,6 +184,7 @@ add_llvm_target(AMDGPUCodeGen GlobalISel HipStdPar IPO + IRPrinter MC MIRParser Passes diff --git a/llvm/lib/Target/AMDGPU/R600CodeGenPassBuilder.cpp b/llvm/lib/Target/AMDGPU/R600CodeGenPassBuilder.cpp new file mode 100644 index 000000000000..a57b3aa0adb1 --- /dev/null +++ b/llvm/lib/Target/AMDGPU/R600CodeGenPassBuilder.cpp @@ -0,0 +1,33 @@ +//===-- R600CodeGenPassBuilder.cpp ------ Build R600 CodeGen pipeline -----===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "R600CodeGenPassBuilder.h" +#include "R600TargetMachine.h" + +using namespace llvm; + +R600CodeGenPassBuilder::R600CodeGenPassBuilder( + R600TargetMachine &TM, const CGPassBuilderOption &Opts, + PassInstrumentationCallbacks *PIC) + : CodeGenPassBuilder(TM, Opts, PIC) { + Opt.RequiresCodeGenSCCOrder = true; +} + +void R600CodeGenPassBuilder::addPreISel(AddIRPass &addPass) const { + // TODO: Add passes pre instruction selection. +} + +void R600CodeGenPassBuilder::addAsmPrinter(AddMachinePass &addPass, + CreateMCStreamer) const { + // TODO: Add AsmPrinter. +} + +Error R600CodeGenPassBuilder::addInstSelector(AddMachinePass &) const { + // TODO: Add instruction selector. + return Error::success(); +} diff --git a/llvm/lib/Target/AMDGPU/R600CodeGenPassBuilder.h b/llvm/lib/Target/AMDGPU/R600CodeGenPassBuilder.h new file mode 100644 index 000000000000..be7c935c094d --- /dev/null +++ b/llvm/lib/Target/AMDGPU/R600CodeGenPassBuilder.h @@ -0,0 +1,32 @@ +//===-- R600CodeGenPassBuilder.h -- Build R600 CodeGen pipeline -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_AMDGPU_R600CODEGENPASSBUILDER_H +#define LLVM_LIB_TARGET_AMDGPU_R600CODEGENPASSBUILDER_H + +#include "llvm/MC/MCStreamer.h" +#include "llvm/Passes/CodeGenPassBuilder.h" + +namespace llvm { + +class R600TargetMachine; + +class R600CodeGenPassBuilder + : public CodeGenPassBuilder { +public: + R600CodeGenPassBuilder(R600TargetMachine &TM, const CGPassBuilderOption &Opts, + PassInstrumentationCallbacks *PIC); + + void addPreISel(AddIRPass &addPass) const; + void addAsmPrinter(AddMachinePass &, CreateMCStreamer) const; + Error addInstSelector(AddMachinePass &) const; +}; + +} // namespace llvm + +#endif // LLVM_LIB_TARGET_AMDGPU_R600CODEGENPASSBUILDER_H diff --git a/llvm/lib/Target/AMDGPU/R600TargetMachine.cpp b/llvm/lib/Target/AMDGPU/R600TargetMachine.cpp index 2461263866a9..c550cfaf06c1 100644 --- a/llvm/lib/Target/AMDGPU/R600TargetMachine.cpp +++ b/llvm/lib/Target/AMDGPU/R600TargetMachine.cpp @@ -15,6 +15,7 @@ #include "R600TargetMachine.h" #include "AMDGPUTargetMachine.h" #include "R600.h" +#include "R600CodeGenPassBuilder.h" #include "R600MachineScheduler.h" #include "R600TargetTransformInfo.h" #include "llvm/Transforms/Scalar.h" @@ -144,3 +145,11 @@ void R600PassConfig::addPreEmitPass() { TargetPassConfig *R600TargetMachine::createPassConfig(PassManagerBase &PM) { return new R600PassConfig(*this, PM); } + +Error R600TargetMachine::buildCodeGenPipeline( + ModulePassManager &MPM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, + CodeGenFileType FileType, const CGPassBuilderOption &Opts, + PassInstrumentationCallbacks *PIC) { + R600CodeGenPassBuilder CGPB(*this, Opts, PIC); + return CGPB.buildPipeline(MPM, Out, DwoOut, FileType); +} diff --git a/llvm/lib/Target/AMDGPU/R600TargetMachine.h b/llvm/lib/Target/AMDGPU/R600TargetMachine.h index af8dcb848867..29e370edef2c 100644 --- a/llvm/lib/Target/AMDGPU/R600TargetMachine.h +++ b/llvm/lib/Target/AMDGPU/R600TargetMachine.h @@ -38,6 +38,12 @@ public: TargetPassConfig *createPassConfig(PassManagerBase &PM) override; + Error buildCodeGenPipeline(ModulePassManager &MPM, raw_pwrite_stream &Out, + raw_pwrite_stream *DwoOut, + CodeGenFileType FileType, + const CGPassBuilderOption &Opt, + PassInstrumentationCallbacks *PIC) override; + const TargetSubtargetInfo *getSubtargetImpl(const Function &) const override; TargetTransformInfo getTargetTransformInfo(const Function &F) const override; -- GitLab From ef890572f379273da09db964b9ea1b67aa324762 Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Sun, 19 May 2024 07:57:11 +0000 Subject: [PATCH 014/793] [gn build] Port b4ba3fe0068b --- llvm/utils/gn/secondary/llvm/lib/Target/AMDGPU/BUILD.gn | 2 ++ 1 file changed, 2 insertions(+) diff --git a/llvm/utils/gn/secondary/llvm/lib/Target/AMDGPU/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Target/AMDGPU/BUILD.gn index dad4f028236d..c859b887828f 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Target/AMDGPU/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Target/AMDGPU/BUILD.gn @@ -138,6 +138,7 @@ static_library("LLVMAMDGPUCodeGen") { "AMDGPUAtomicOptimizer.cpp", "AMDGPUAttributor.cpp", "AMDGPUCallLowering.cpp", + "AMDGPUCodeGenPassBuilder.cpp", "AMDGPUCodeGenPrepare.cpp", "AMDGPUCombinerHelper.cpp", "AMDGPUCtorDtorLowering.cpp", @@ -206,6 +207,7 @@ static_library("LLVMAMDGPUCodeGen") { "GCNVOPDUtils.cpp", "R600AsmPrinter.cpp", "R600ClauseMergePass.cpp", + "R600CodeGenPassBuilder.cpp", "R600ControlFlowFinalizer.cpp", "R600EmitClauseMarkers.cpp", "R600ExpandSpecialInstrs.cpp", -- GitLab From 9940620f6eab50deeaed0d976b2ea0afd007ba24 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Sun, 19 May 2024 16:08:58 +0800 Subject: [PATCH 015/793] [GISel][RISCV] Legalize G_CONSTANT_FOLD_BARRIER (#89960) This patch supports `G_CONSTANT_FOLD_BARRIER` on RISCV to generate the following inst seq without crash: ``` define i64 @xor_and_i64(i64 %x) { entry: %y = and i64 %x, 16383 %z = xor i64 %y, 16368 ret i64 %z } ``` --- .../Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 2 +- .../legalizer/legalize-constbarrier-rv32.mir | 51 +++++++++++ .../legalizer/legalize-constbarrier-rv64.mir | 87 +++++++++++++++++++ 3 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-constbarrier-rv32.mir create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-constbarrier-rv64.mir diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp index 38c1f9868d7d..adc68e9ee4a8 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp +++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp @@ -227,7 +227,7 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) ConstantActions.widenScalarToNextPow2(0).clampScalar(0, s32, sXLen); // TODO: transform illegal vector types into legal vector type - getActionDefinitionsBuilder(G_IMPLICIT_DEF) + getActionDefinitionsBuilder({G_IMPLICIT_DEF, G_CONSTANT_FOLD_BARRIER}) .legalFor({s32, sXLen, p0}) .legalIf(typeIsLegalBoolVec(0, BoolVecTys, ST)) .legalIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST)) diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-constbarrier-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-constbarrier-rv32.mir new file mode 100644 index 000000000000..6b1fc2042e2b --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-constbarrier-rv32.mir @@ -0,0 +1,51 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 +# RUN: llc -mtriple=riscv32 -mattr=+v -run-pass=legalizer %s -o - | FileCheck %s +--- +name: constbarrier_i32 +body: | + bb.0.entry: + ; CHECK-LABEL: name: constbarrier_i32 + ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16368 + ; CHECK-NEXT: [[CONSTANT_FOLD_BARRIER:%[0-9]+]]:_(s32) = G_CONSTANT_FOLD_BARRIER [[C]] + ; CHECK-NEXT: $x10 = COPY [[CONSTANT_FOLD_BARRIER]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:_(s32) = G_CONSTANT i32 16368 + %2:_(s32) = G_CONSTANT_FOLD_BARRIER %1 + $x10 = COPY %2(s32) + PseudoRET implicit $x10 + +... +--- +name: constbarrier_nxv2i1 +body: | + bb.0.entry: + ; CHECK-LABEL: name: constbarrier_nxv2i1 + ; CHECK: [[VMSET_VL:%[0-9]+]]:_() = G_VMSET_VL $x0 + ; CHECK-NEXT: [[VMCLR_VL:%[0-9]+]]:_() = G_VMCLR_VL $x0 + ; CHECK-NEXT: [[CONSTANT_FOLD_BARRIER:%[0-9]+]]:_() = G_CONSTANT_FOLD_BARRIER [[VMCLR_VL]] + ; CHECK-NEXT: $v8 = COPY [[CONSTANT_FOLD_BARRIER]]() + ; CHECK-NEXT: PseudoRET implicit $v8 + %1:_(s1) = G_CONSTANT i1 0 + %2:_() = G_SPLAT_VECTOR %1(s1) + %3:_() = G_CONSTANT_FOLD_BARRIER %2 + $v8 = COPY %3() + PseudoRET implicit $v8 + +... +--- +name: constbarrier_nxv2i32 +body: | + bb.0.entry: + ; CHECK-LABEL: name: constbarrier_nxv2i32 + ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[SPLAT_VECTOR:%[0-9]+]]:_() = G_SPLAT_VECTOR [[C]](s32) + ; CHECK-NEXT: [[CONSTANT_FOLD_BARRIER:%[0-9]+]]:_() = G_CONSTANT_FOLD_BARRIER [[SPLAT_VECTOR]] + ; CHECK-NEXT: $v8 = COPY [[CONSTANT_FOLD_BARRIER]]() + ; CHECK-NEXT: PseudoRET implicit $v8 + %1:_(s32) = G_CONSTANT i32 0 + %2:_() = G_SPLAT_VECTOR %1(s32) + %3:_() = G_CONSTANT_FOLD_BARRIER %2 + $v8 = COPY %3() + PseudoRET implicit $v8 + +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-constbarrier-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-constbarrier-rv64.mir new file mode 100644 index 000000000000..de6a82beee2a --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-constbarrier-rv64.mir @@ -0,0 +1,87 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 +# RUN: llc -mtriple=riscv64 -mattr=+v -run-pass=legalizer %s -o - | FileCheck %s +--- +name: constbarrier_i32 +body: | + bb.0.entry: + ; CHECK-LABEL: name: constbarrier_i32 + ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16368 + ; CHECK-NEXT: [[CONSTANT_FOLD_BARRIER:%[0-9]+]]:_(s32) = G_CONSTANT_FOLD_BARRIER [[C]] + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[CONSTANT_FOLD_BARRIER]](s32) + ; CHECK-NEXT: $x10 = COPY [[ANYEXT]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:_(s32) = G_CONSTANT i32 16368 + %2:_(s32) = G_CONSTANT_FOLD_BARRIER %1 + %3:_(s64) = G_ANYEXT %2(s32) + $x10 = COPY %3(s64) + PseudoRET implicit $x10 + +... +--- +name: constbarrier_i64 +body: | + bb.0.entry: + ; CHECK-LABEL: name: constbarrier_i64 + ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 16368 + ; CHECK-NEXT: [[CONSTANT_FOLD_BARRIER:%[0-9]+]]:_(s64) = G_CONSTANT_FOLD_BARRIER [[C]] + ; CHECK-NEXT: $x10 = COPY [[CONSTANT_FOLD_BARRIER]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:_(s64) = G_CONSTANT i64 16368 + %2:_(s64) = G_CONSTANT_FOLD_BARRIER %1 + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: constbarrier_nxv2i1 +body: | + bb.0.entry: + ; CHECK-LABEL: name: constbarrier_nxv2i1 + ; CHECK: [[VMSET_VL:%[0-9]+]]:_() = G_VMSET_VL $x0 + ; CHECK-NEXT: [[VMCLR_VL:%[0-9]+]]:_() = G_VMCLR_VL $x0 + ; CHECK-NEXT: [[CONSTANT_FOLD_BARRIER:%[0-9]+]]:_() = G_CONSTANT_FOLD_BARRIER [[VMCLR_VL]] + ; CHECK-NEXT: $v8 = COPY [[CONSTANT_FOLD_BARRIER]]() + ; CHECK-NEXT: PseudoRET implicit $v8 + %1:_(s1) = G_CONSTANT i1 0 + %2:_() = G_SPLAT_VECTOR %1(s1) + %3:_() = G_CONSTANT_FOLD_BARRIER %2 + $v8 = COPY %3() + PseudoRET implicit $v8 + +... +--- +name: constbarrier_nxv2i32 +body: | + bb.0.entry: + ; CHECK-LABEL: name: constbarrier_nxv2i32 + ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[C]](s32) + ; CHECK-NEXT: [[SPLAT_VECTOR:%[0-9]+]]:_() = G_SPLAT_VECTOR [[ANYEXT]](s64) + ; CHECK-NEXT: [[CONSTANT_FOLD_BARRIER:%[0-9]+]]:_() = G_CONSTANT_FOLD_BARRIER [[SPLAT_VECTOR]] + ; CHECK-NEXT: $v8 = COPY [[CONSTANT_FOLD_BARRIER]]() + ; CHECK-NEXT: PseudoRET implicit $v8 + %1:_(s32) = G_CONSTANT i32 0 + %2:_() = G_SPLAT_VECTOR %1(s32) + %3:_() = G_CONSTANT_FOLD_BARRIER %2 + $v8 = COPY %3() + PseudoRET implicit $v8 + +... +--- +name: constbarrier_nxv2i64 +body: | + bb.0.entry: + ; CHECK-LABEL: name: constbarrier_nxv2i64 + ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; CHECK-NEXT: [[SPLAT_VECTOR:%[0-9]+]]:_() = G_SPLAT_VECTOR [[C]](s64) + ; CHECK-NEXT: [[CONSTANT_FOLD_BARRIER:%[0-9]+]]:_() = G_CONSTANT_FOLD_BARRIER [[SPLAT_VECTOR]] + ; CHECK-NEXT: $v8m2 = COPY [[CONSTANT_FOLD_BARRIER]]() + ; CHECK-NEXT: PseudoRET implicit $v8m2 + %0:_() = G_IMPLICIT_DEF + %1:_(s64) = G_CONSTANT i64 0 + %2:_() = G_SPLAT_VECTOR %1(s64) + %3:_() = G_CONSTANT_FOLD_BARRIER %2() + $v8m2 = COPY %3() + PseudoRET implicit $v8m2 + +... -- GitLab From 8b8a38a7b426fc724804602d7635134a0c63f08c Mon Sep 17 00:00:00 2001 From: David Green Date: Sun, 19 May 2024 10:18:26 +0100 Subject: [PATCH 016/793] [VectorCombine] Additional extend tests for shuffleToIdentity. NFC --- .../AArch64/shuffletoidentity.ll | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll b/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll index b58f92d70936..bb333941abf7 100644 --- a/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll +++ b/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll @@ -465,6 +465,125 @@ define void @exttrunc(<8 x i32> %a, <8 x i32> %b, ptr %p) { ret void } +define void @zext(<8 x i16> %a, <8 x i16> %b, ptr %p) { +; CHECK-LABEL: @zext( +; CHECK-NEXT: [[AB:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> poison, <4 x i32> +; CHECK-NEXT: [[AT:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> poison, <4 x i32> +; CHECK-NEXT: [[BB:%.*]] = shufflevector <8 x i16> [[B:%.*]], <8 x i16> poison, <4 x i32> +; CHECK-NEXT: [[BT:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> poison, <4 x i32> +; CHECK-NEXT: [[AB1:%.*]] = zext <4 x i16> [[AB]] to <4 x i32> +; CHECK-NEXT: [[AT1:%.*]] = zext <4 x i16> [[AT]] to <4 x i32> +; CHECK-NEXT: [[BB1:%.*]] = zext <4 x i16> [[BB]] to <4 x i32> +; CHECK-NEXT: [[BT1:%.*]] = zext <4 x i16> [[BT]] to <4 x i32> +; CHECK-NEXT: [[ABB:%.*]] = add <4 x i32> [[AB1]], [[BB1]] +; CHECK-NEXT: [[ABT:%.*]] = add <4 x i32> [[AT1]], [[BT1]] +; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[ABB]], <4 x i32> [[ABT]], <8 x i32> +; CHECK-NEXT: store <8 x i32> [[R]], ptr [[P:%.*]], align 32 +; CHECK-NEXT: ret void +; + %ab = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> + %at = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> + %bb = shufflevector <8 x i16> %b, <8 x i16> poison, <4 x i32> + %bt = shufflevector <8 x i16> %b, <8 x i16> poison, <4 x i32> + %ab1 = zext <4 x i16> %ab to <4 x i32> + %at1 = zext <4 x i16> %at to <4 x i32> + %bb1 = zext <4 x i16> %bb to <4 x i32> + %bt1 = zext <4 x i16> %bt to <4 x i32> + %abb = add <4 x i32> %ab1, %bb1 + %abt = add <4 x i32> %at1, %bt1 + %r = shufflevector <4 x i32> %abb, <4 x i32> %abt, <8 x i32> + store <8 x i32> %r, ptr %p + ret void +} + +define void @sext(<8 x i16> %a, <8 x i16> %b, ptr %p) { +; CHECK-LABEL: @sext( +; CHECK-NEXT: [[AB:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> poison, <4 x i32> +; CHECK-NEXT: [[AT:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> poison, <4 x i32> +; CHECK-NEXT: [[BB:%.*]] = shufflevector <8 x i16> [[B:%.*]], <8 x i16> poison, <4 x i32> +; CHECK-NEXT: [[BT:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> poison, <4 x i32> +; CHECK-NEXT: [[AB1:%.*]] = sext <4 x i16> [[AB]] to <4 x i32> +; CHECK-NEXT: [[AT1:%.*]] = sext <4 x i16> [[AT]] to <4 x i32> +; CHECK-NEXT: [[BB1:%.*]] = sext <4 x i16> [[BB]] to <4 x i32> +; CHECK-NEXT: [[BT1:%.*]] = sext <4 x i16> [[BT]] to <4 x i32> +; CHECK-NEXT: [[ABB:%.*]] = add <4 x i32> [[AB1]], [[BB1]] +; CHECK-NEXT: [[ABT:%.*]] = add <4 x i32> [[AT1]], [[BT1]] +; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[ABB]], <4 x i32> [[ABT]], <8 x i32> +; CHECK-NEXT: store <8 x i32> [[R]], ptr [[P:%.*]], align 32 +; CHECK-NEXT: ret void +; + %ab = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> + %at = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> + %bb = shufflevector <8 x i16> %b, <8 x i16> poison, <4 x i32> + %bt = shufflevector <8 x i16> %b, <8 x i16> poison, <4 x i32> + %ab1 = sext <4 x i16> %ab to <4 x i32> + %at1 = sext <4 x i16> %at to <4 x i32> + %bb1 = sext <4 x i16> %bb to <4 x i32> + %bt1 = sext <4 x i16> %bt to <4 x i32> + %abb = add <4 x i32> %ab1, %bb1 + %abt = add <4 x i32> %at1, %bt1 + %r = shufflevector <4 x i32> %abb, <4 x i32> %abt, <8 x i32> + store <8 x i32> %r, ptr %p + ret void +} + +define void @szext(<8 x i32> %a, <8 x i32> %b, ptr %p) { +; CHECK-LABEL: @szext( +; CHECK-NEXT: [[AB:%.*]] = shufflevector <8 x i32> [[A:%.*]], <8 x i32> poison, <4 x i32> +; CHECK-NEXT: [[AT:%.*]] = shufflevector <8 x i32> [[A]], <8 x i32> poison, <4 x i32> +; CHECK-NEXT: [[AB1:%.*]] = sext <4 x i32> [[AB]] to <4 x i64> +; CHECK-NEXT: [[AT1:%.*]] = zext <4 x i32> [[AT]] to <4 x i64> +; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i64> [[AB1]], <4 x i64> [[AT1]], <8 x i32> +; CHECK-NEXT: store <8 x i64> [[R]], ptr [[P:%.*]], align 64 +; CHECK-NEXT: ret void +; + %ab = shufflevector <8 x i32> %a, <8 x i32> poison, <4 x i32> + %at = shufflevector <8 x i32> %a, <8 x i32> poison, <4 x i32> + %ab1 = sext <4 x i32> %ab to <4 x i64> + %at1 = zext <4 x i32> %at to <4 x i64> + %r = shufflevector <4 x i64> %ab1, <4 x i64> %at1, <8 x i32> + store <8 x i64> %r, ptr %p + ret void +} + +define void @zext_types(<8 x i16> %a, <8 x i32> %b, ptr %p) { +; CHECK-LABEL: @zext_types( +; CHECK-NEXT: [[AB:%.*]] = shufflevector <8 x i16> [[A:%.*]], <8 x i16> poison, <4 x i32> +; CHECK-NEXT: [[AT:%.*]] = shufflevector <8 x i32> [[B:%.*]], <8 x i32> poison, <4 x i32> +; CHECK-NEXT: [[AB1:%.*]] = zext <4 x i16> [[AB]] to <4 x i64> +; CHECK-NEXT: [[AT1:%.*]] = zext <4 x i32> [[AT]] to <4 x i64> +; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i64> [[AB1]], <4 x i64> [[AT1]], <8 x i32> +; CHECK-NEXT: store <8 x i64> [[R]], ptr [[P:%.*]], align 64 +; CHECK-NEXT: ret void +; + %ab = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> + %at = shufflevector <8 x i32> %b, <8 x i32> poison, <4 x i32> + %ab1 = zext <4 x i16> %ab to <4 x i64> + %at1 = zext <4 x i32> %at to <4 x i64> + %r = shufflevector <4 x i64> %ab1, <4 x i64> %at1, <8 x i32> + store <8 x i64> %r, ptr %p + ret void +} + +define void @trunc(<8 x i64> %a, <8 x i64> %b, ptr %p) { +; CHECK-LABEL: @trunc( +; CHECK-NEXT: [[AB:%.*]] = shufflevector <8 x i64> [[A:%.*]], <8 x i64> poison, <4 x i32> +; CHECK-NEXT: [[AT:%.*]] = shufflevector <8 x i64> [[A]], <8 x i64> poison, <4 x i32> +; CHECK-NEXT: [[ABB1:%.*]] = trunc <4 x i64> [[AB]] to <4 x i32> +; CHECK-NEXT: [[ABT1:%.*]] = trunc <4 x i64> [[AT]] to <4 x i32> +; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[ABB1]], <4 x i32> [[ABT1]], <8 x i32> +; CHECK-NEXT: store <8 x i32> [[R]], ptr [[P:%.*]], align 32 +; CHECK-NEXT: ret void +; + %ab = shufflevector <8 x i64> %a, <8 x i64> poison, <4 x i32> + %at = shufflevector <8 x i64> %a, <8 x i64> poison, <4 x i32> + %abb1 = trunc <4 x i64> %ab to <4 x i32> + %abt1 = trunc <4 x i64> %at to <4 x i32> + %r = shufflevector <4 x i32> %abb1, <4 x i32> %abt1, <8 x i32> + store <8 x i32> %r, ptr %p + ret void +} + define <8 x i8> @intrinsics_minmax(<8 x i8> %a, <8 x i8> %b) { ; CHECK-LABEL: @intrinsics_minmax( ; CHECK-NEXT: [[TMP1:%.*]] = call <8 x i8> @llvm.smin.v8i8(<8 x i8> [[A:%.*]], <8 x i8> [[B:%.*]]) @@ -624,4 +743,26 @@ entry: ret void } +define <4 x i8> @singleop(<4 x i8> %a, <4 x i8> %b) { +; CHECK-LABEL: @singleop( +; CHECK-NEXT: [[A1:%.*]] = shufflevector <4 x i8> [[A:%.*]], <4 x i8> poison, <4 x i32> +; CHECK-NEXT: [[B1:%.*]] = shufflevector <4 x i8> [[B:%.*]], <4 x i8> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[A2:%.*]] = zext <4 x i8> [[A1]] to <4 x i16> +; CHECK-NEXT: [[B2:%.*]] = zext <4 x i8> [[B1]] to <4 x i16> +; CHECK-NEXT: [[AB:%.*]] = add <4 x i16> [[A2]], [[B2]] +; CHECK-NEXT: [[T:%.*]] = trunc <4 x i16> [[AB]] to <4 x i8> +; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[T]], <4 x i8> poison, <4 x i32> +; CHECK-NEXT: ret <4 x i8> [[R]] +; + %a1 = shufflevector <4 x i8> %a, <4 x i8> poison, <4 x i32> + %b1 = shufflevector <4 x i8> %b, <4 x i8> poison, <4 x i32> + %a2 = zext <4 x i8> %a1 to <4 x i16> + %b2 = zext <4 x i8> %b1 to <4 x i16> + %ab = add <4 x i16> %a2, %b2 + %t = trunc <4 x i16> %ab to <4 x i8> + %r = shufflevector <4 x i8> %t, <4 x i8> poison, <4 x i32> + ret <4 x i8> %r +} + + declare void @use(<4 x i8>) -- GitLab From 689bba1eec31fa236e2febaa4bcf46bc89ba432b Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sun, 19 May 2024 10:25:01 +0100 Subject: [PATCH 017/793] [DAG] canCreateUndefOrPoison - merge INSERT_VECTOR_ELT/EXTRACT_VECTOR_ELT cases. NFC. The only difference is the operand index for the element index variable. --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 247f52370e4c..6a4ff741af10 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -5241,17 +5241,12 @@ bool SelectionDAG::canCreateUndefOrPoison(SDValue Op, const APInt &DemandedElts, // Check if we demand any upper (undef) elements. return !PoisonOnly && DemandedElts.ugt(1); + case ISD::INSERT_VECTOR_ELT: case ISD::EXTRACT_VECTOR_ELT: { // Ensure that the element index is in bounds. EVT VecVT = Op.getOperand(0).getValueType(); - KnownBits KnownIdx = computeKnownBits(Op.getOperand(1), Depth + 1); - return KnownIdx.getMaxValue().uge(VecVT.getVectorMinNumElements()); - } - - case ISD::INSERT_VECTOR_ELT:{ - // Ensure that the element index is in bounds. - EVT VecVT = Op.getOperand(0).getValueType(); - KnownBits KnownIdx = computeKnownBits(Op.getOperand(2), Depth + 1); + SDValue Idx = Op.getOperand(Opcode == ISD::INSERT_VECTOR_ELT ? 2 : 1); + KnownBits KnownIdx = computeKnownBits(Idx, Depth + 1); return KnownIdx.getMaxValue().uge(VecVT.getVectorMinNumElements()); } -- GitLab From 7fc524fe080a69e79bd1ce8925e680350b7e9d44 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Sun, 19 May 2024 02:43:55 -0700 Subject: [PATCH 018/793] [ctx_profile] Pass lib path into test Fixes build after cfe9deb1353021a1c1fe4731ec3e90f702dbd43d on https://lab.llvm.org/buildbot/#/builders/37/builds/34828 --- .../test/ctx_profile/TestCases/generate-context.cpp | 2 +- compiler-rt/test/ctx_profile/lit.cfg.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler-rt/test/ctx_profile/TestCases/generate-context.cpp b/compiler-rt/test/ctx_profile/TestCases/generate-context.cpp index 981d6170091c..797b87186065 100644 --- a/compiler-rt/test/ctx_profile/TestCases/generate-context.cpp +++ b/compiler-rt/test/ctx_profile/TestCases/generate-context.cpp @@ -5,7 +5,7 @@ // RUN: cp %llvm_src/include/llvm/ProfileData/CtxInstrContextNode.h %t_include/ // // Compile with ctx instrumentation "on". We treat "theRoot" as callgraph root. -// RUN: %clangxx %s -lclang_rt.ctx_profile -I%t_include -O2 -o %t.bin -mllvm -profile-context-root=theRoot +// RUN: %clangxx %s %ctxprofilelib -I%t_include -O2 -o %t.bin -mllvm -profile-context-root=theRoot // // Run the binary, and observe the profile fetch handler's output. // RUN: %t.bin | FileCheck %s diff --git a/compiler-rt/test/ctx_profile/lit.cfg.py b/compiler-rt/test/ctx_profile/lit.cfg.py index bf62093601f1..3034fadbb7a6 100644 --- a/compiler-rt/test/ctx_profile/lit.cfg.py +++ b/compiler-rt/test/ctx_profile/lit.cfg.py @@ -33,3 +33,10 @@ config.suffixes = [".c", ".cpp", ".test"] config.substitutions.append( ("%clangxx ", " ".join([config.clang] + config.cxx_mode_flags) + " -ldl -lpthread ") ) + +config.substitutions.append( + ( + "%ctxprofilelib", + "-L%s -lclang_rt.ctx_profile%s" % (config.compiler_rt_libdir, config.target_suffix) + ) +) -- GitLab From e0217ee7829cf49bc0caa8b814f6acc4c4b0836d Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sun, 19 May 2024 11:06:02 +0100 Subject: [PATCH 019/793] [DAG] canCreateUndefOrPoison - only compute extract/index vector elt index knownbits when not poison We were calling computeKnownBits to determine the bounds of the element index without ensuring that it wasn't poison, meaning if we did freeze the index, isGuaranteedNotToBeUndefOrPoison would then fail as we can't call computeKnownBits through FREEZE for potentially poison values. Fixes #92569 --- .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 8 +++-- llvm/test/CodeGen/X86/pr92569.ll | 29 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/X86/pr92569.ll diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 6a4ff741af10..2e1f4b7e5b37 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -5246,8 +5246,12 @@ bool SelectionDAG::canCreateUndefOrPoison(SDValue Op, const APInt &DemandedElts, // Ensure that the element index is in bounds. EVT VecVT = Op.getOperand(0).getValueType(); SDValue Idx = Op.getOperand(Opcode == ISD::INSERT_VECTOR_ELT ? 2 : 1); - KnownBits KnownIdx = computeKnownBits(Idx, Depth + 1); - return KnownIdx.getMaxValue().uge(VecVT.getVectorMinNumElements()); + if (isGuaranteedNotToBeUndefOrPoison(Idx, DemandedElts, PoisonOnly, + Depth + 1)) { + KnownBits KnownIdx = computeKnownBits(Idx, Depth + 1); + return KnownIdx.getMaxValue().uge(VecVT.getVectorMinNumElements()); + } + return true; } case ISD::VECTOR_SHUFFLE: { diff --git a/llvm/test/CodeGen/X86/pr92569.ll b/llvm/test/CodeGen/X86/pr92569.ll new file mode 100644 index 000000000000..f91063089e3a --- /dev/null +++ b/llvm/test/CodeGen/X86/pr92569.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=x86_64-linux-gnu | FileCheck %s + +define void @PR92569(i64 %arg, <8 x i8> %arg1) { +; CHECK-LABEL: PR92569: +; CHECK: # %bb.0: +; CHECK-NEXT: testq %rdi, %rdi +; CHECK-NEXT: je .LBB0_1 +; CHECK-NEXT: # %bb.2: # %cond.false +; CHECK-NEXT: rep bsfq %rdi, %rax +; CHECK-NEXT: jmp .LBB0_3 +; CHECK-NEXT: .LBB0_1: +; CHECK-NEXT: movl $64, %eax +; CHECK-NEXT: .LBB0_3: # %cond.end +; CHECK-NEXT: shrb $3, %al +; CHECK-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) +; CHECK-NEXT: movzbl %al, %eax +; CHECK-NEXT: movzbl -24(%rsp,%rax), %eax +; CHECK-NEXT: movl %eax, 0 +; CHECK-NEXT: retq + %cttz = call i64 @llvm.cttz.i64(i64 %arg, i1 false) + %trunc = trunc i64 %cttz to i8 + %lshr = lshr i8 %trunc, 3 + %extractelement = extractelement <8 x i8> %arg1, i8 %lshr + %freeze = freeze i8 %extractelement + %zext = zext i8 %freeze to i32 + store i32 %zext, ptr addrspace(1) null, align 4 + ret void +} -- GitLab From 9f5c8de3864b0be27a8b36cd891c5a28a3acfd27 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sun, 19 May 2024 11:30:20 +0100 Subject: [PATCH 020/793] [DAG] visitAVG - rewrite "fold (avgfloor x, 0) -> x >> 1" to use SDPatternMatch No need for this to be vector specific, and its more likely that scalar cases will appear after #92096 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 2b1dec8205b7..bf85212e6a92 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -5211,30 +5211,28 @@ SDValue DAGCombiner::visitAVG(SDNode *N) { !DAG.isConstantIntBuildVectorOrConstantInt(N1)) return DAG.getNode(Opcode, DL, N->getVTList(), N1, N0); - if (VT.isVector()) { + if (VT.isVector()) if (SDValue FoldedVOp = SimplifyVBinOp(N, DL)) return FoldedVOp; - // fold (avgfloor x, 0) -> x >> 1 - if (ISD::isConstantSplatVectorAllZeros(N1.getNode())) { - if (Opcode == ISD::AVGFLOORS) - return DAG.getNode(ISD::SRA, DL, VT, N0, DAG.getConstant(1, DL, VT)); - if (Opcode == ISD::AVGFLOORU) - return DAG.getNode(ISD::SRL, DL, VT, N0, DAG.getConstant(1, DL, VT)); - } - } - // fold (avg x, undef) -> x if (N0.isUndef()) return N1; if (N1.isUndef()) return N0; - // Fold (avg x, x) --> x + // fold (avg x, x) --> x if (N0 == N1 && Level >= AfterLegalizeTypes) return N0; - // TODO If we use avg for scalars anywhere, we can add (avgfl x, 0) -> x >> 1 + // fold (avgfloor x, 0) -> x >> 1 + SDValue X; + if (sd_match(N, m_c_BinOp(ISD::AVGFLOORS, m_Value(X), m_Zero()))) + return DAG.getNode(ISD::SRA, DL, VT, X, + DAG.getShiftAmountConstant(1, VT, DL)); + if (sd_match(N, m_c_BinOp(ISD::AVGFLOORU, m_Value(X), m_Zero()))) + return DAG.getNode(ISD::SRL, DL, VT, X, + DAG.getShiftAmountConstant(1, VT, DL)); return SDValue(); } -- GitLab From 7273ad123850a7b44c0625d098ebb49153bf855a Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sun, 19 May 2024 11:49:51 +0100 Subject: [PATCH 021/793] [DAG] visitABD - rewrite "(abs x, 0)" folds to use SDPatternMatch No need for this to be vector specific, and its more likely that scalar cases will appear after #92576 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index bf85212e6a92..8607b5017535 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -5253,24 +5253,25 @@ SDValue DAGCombiner::visitABD(SDNode *N) { !DAG.isConstantIntBuildVectorOrConstantInt(N1)) return DAG.getNode(Opcode, DL, N->getVTList(), N1, N0); - if (VT.isVector()) { + if (VT.isVector()) if (SDValue FoldedVOp = SimplifyVBinOp(N, DL)) return FoldedVOp; - // fold (abds x, 0) -> abs x - // fold (abdu x, 0) -> x - if (ISD::isConstantSplatVectorAllZeros(N1.getNode())) { - if (Opcode == ISD::ABDS) - return DAG.getNode(ISD::ABS, DL, VT, N0); - if (Opcode == ISD::ABDU) - return N0; - } - } - // fold (abd x, undef) -> 0 if (N0.isUndef() || N1.isUndef()) return DAG.getConstant(0, DL, VT); + SDValue X; + + // fold (abds x, 0) -> abs x + if (sd_match(N, m_c_BinOp(ISD::ABDS, m_Value(X), m_Zero())) && + (!LegalOperations || hasOperation(ISD::ABS, VT))) + return DAG.getNode(ISD::ABS, DL, VT, X); + + // fold (abdu x, 0) -> x + if (sd_match(N, m_c_BinOp(ISD::ABDU, m_Value(X), m_Zero()))) + return X; + // fold (abds x, y) -> (abdu x, y) iff both args are known positive if (Opcode == ISD::ABDS && hasOperation(ISD::ABDU, VT) && DAG.SignBitIsZero(N0) && DAG.SignBitIsZero(N1)) -- GitLab From ed9007d0d219726db01f211e9c9ab72fbfe4ecb1 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Sun, 19 May 2024 04:29:11 -0700 Subject: [PATCH 022/793] Revert "[Bounds-Safety] Temporarily relax a `counted_by` attribute restriction on flexible array members" Together with 0ec3b972e58bcbcdc1bebe1696ea37f2931287c3 breaks https://lab.llvm.org/buildbot/#/builders/5/builds/43403 Issue #92687 This reverts commit cef6387e52578366c2332275dad88b9953b55336. --- clang/include/clang/Basic/DiagnosticGroups.td | 4 ---- .../include/clang/Basic/DiagnosticSemaKinds.td | 8 +------- clang/lib/Sema/SemaDeclAttr.cpp | 17 ++--------------- clang/test/Sema/attr-counted-by-vla.c | 9 +++------ 4 files changed, 6 insertions(+), 32 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 4fad4d1a0eca..4cb4f3d999f7 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1447,10 +1447,6 @@ def FunctionMultiVersioning def NoDeref : DiagGroup<"noderef">; -// -fbounds-safety and bounds annotation related warnings -def BoundsSafetyCountedByEltTyUnknownSize : - DiagGroup<"bounds-safety-counted-by-elt-type-unknown-size">; - // A group for cross translation unit static analysis related warnings. def CrossTU : DiagGroup<"ctu">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1efa3af121c1..8e6596410c5d 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6552,7 +6552,7 @@ def err_counted_by_attr_refer_to_union : Error< def note_flexible_array_counted_by_attr_field : Note< "field %0 declared here">; def err_counted_by_attr_pointee_unknown_size : Error< - "'counted_by' %select{cannot|should not}3 be applied to %select{" + "'counted_by' cannot be applied to %select{" "a pointer with pointee|" // pointer "an array with element}0" // array " of unknown size because %1 is %select{" @@ -6561,14 +6561,8 @@ def err_counted_by_attr_pointee_unknown_size : Error< "a function type|" // CountedByInvalidPointeeTypeKind::FUNCTION // CountedByInvalidPointeeTypeKind::FLEXIBLE_ARRAY_MEMBER "a struct type with a flexible array member" - "%select{|. This will be an error in a future compiler version}3" - "" "}2">; -def warn_counted_by_attr_elt_type_unknown_size : - Warning, - InGroup; - let CategoryName = "ARC Semantic Issue" in { // ARC-mode diagnostics. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index e816ea3647a7..c8b71631076b 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -8687,7 +8687,6 @@ static bool CheckCountedByAttrOnField( // Note: The `Decl::isFlexibleArrayMemberLike` check earlier on means // only `PointeeTy->isStructureTypeWithFlexibleArrayMember()` is reachable // when `FieldTy->isArrayType()`. - bool ShouldWarn = false; if (PointeeTy->isIncompleteType()) { InvalidTypeKind = CountedByInvalidPointeeTypeKind::INCOMPLETE; } else if (PointeeTy->isSizelessType()) { @@ -8695,25 +8694,13 @@ static bool CheckCountedByAttrOnField( } else if (PointeeTy->isFunctionType()) { InvalidTypeKind = CountedByInvalidPointeeTypeKind::FUNCTION; } else if (PointeeTy->isStructureTypeWithFlexibleArrayMember()) { - if (FieldTy->isArrayType()) { - // This is a workaround for the Linux kernel that has already adopted - // `counted_by` on a FAM where the pointee is a struct with a FAM. This - // should be an error because computing the bounds of the array cannot be - // done correctly without manually traversing every struct object in the - // array at runtime. To allow the code to be built this error is - // downgraded to a warning. - ShouldWarn = true; - } InvalidTypeKind = CountedByInvalidPointeeTypeKind::FLEXIBLE_ARRAY_MEMBER; } if (InvalidTypeKind != CountedByInvalidPointeeTypeKind::VALID) { - unsigned DiagID = ShouldWarn - ? diag::warn_counted_by_attr_elt_type_unknown_size - : diag::err_counted_by_attr_pointee_unknown_size; - S.Diag(FD->getBeginLoc(), DiagID) + S.Diag(FD->getBeginLoc(), diag::err_counted_by_attr_pointee_unknown_size) << SelectPtrOrArr << PointeeTy << (int)InvalidTypeKind - << (ShouldWarn ? 1 : 0) << FD->getSourceRange(); + << FD->getSourceRange(); return true; } diff --git a/clang/test/Sema/attr-counted-by-vla.c b/clang/test/Sema/attr-counted-by-vla.c index b25f719f3b95..3de6bd55e2d8 100644 --- a/clang/test/Sema/attr-counted-by-vla.c +++ b/clang/test/Sema/attr-counted-by-vla.c @@ -173,24 +173,21 @@ struct has_annotated_VLA { struct buffer_of_structs_with_unnannotated_vla { int count; - // Treating this as a warning is a temporary fix for existing attribute adopters. It **SHOULD BE AN ERROR**. - // expected-warning@+1{{'counted_by' should not be applied to an array with element of unknown size because 'struct has_unannotated_VLA' is a struct type with a flexible array member. This will be an error in a future compiler version}} + // expected-error@+1{{'counted_by' cannot be applied to an array with element of unknown size because 'struct has_unannotated_VLA' is a struct type with a flexible array member}} struct has_unannotated_VLA Arr[] __counted_by(count); }; struct buffer_of_structs_with_annotated_vla { int count; - // Treating this as a warning is a temporary fix for existing attribute adopters. It **SHOULD BE AN ERROR**. - // expected-warning@+1{{'counted_by' should not be applied to an array with element of unknown size because 'struct has_annotated_VLA' is a struct type with a flexible array member. This will be an error in a future compiler version}} + // expected-error@+1{{'counted_by' cannot be applied to an array with element of unknown size because 'struct has_annotated_VLA' is a struct type with a flexible array member}} struct has_annotated_VLA Arr[] __counted_by(count); }; struct buffer_of_const_structs_with_annotated_vla { int count; - // Treating this as a warning is a temporary fix for existing attribute adopters. It **SHOULD BE AN ERROR**. // Make sure the `const` qualifier is printed when printing the element type. - // expected-warning@+1{{'counted_by' should not be applied to an array with element of unknown size because 'const struct has_annotated_VLA' is a struct type with a flexible array member. This will be an error in a future compiler version}} + // expected-error@+1{{'counted_by' cannot be applied to an array with element of unknown size because 'const struct has_annotated_VLA' is a struct type with a flexible array member}} const struct has_annotated_VLA Arr[] __counted_by(count); }; -- GitLab From 6447abe067c8088a5cc093fe872719374e174068 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Sun, 19 May 2024 04:30:22 -0700 Subject: [PATCH 023/793] Revert "[BoundsSafety] Allow 'counted_by' attribute on pointers in structs in C (#90786)" Memory leak: https://lab.llvm.org/buildbot/#/builders/5/builds/43403 Issue #92687 This reverts commit 0ec3b972e58bcbcdc1bebe1696ea37f2931287c3. --- clang/docs/ReleaseNotes.rst | 21 +- clang/include/clang/AST/Type.h | 1 - clang/include/clang/Basic/Attr.td | 3 +- .../clang/Basic/DiagnosticSemaKinds.td | 17 +- clang/include/clang/Parse/Parser.h | 7 +- clang/include/clang/Sema/Sema.h | 3 +- clang/lib/AST/Type.cpp | 10 - clang/lib/Parse/ParseDecl.cpp | 104 +------ clang/lib/Parse/ParseObjc.cpp | 10 +- clang/lib/Sema/SemaDeclAttr.cpp | 82 ++---- clang/lib/Sema/SemaType.cpp | 6 +- clang/lib/Sema/TreeTransform.h | 2 +- .../attr-counted-by-late-parsed-struct-ptrs.c | 45 ---- clang/test/AST/attr-counted-by-struct-ptrs.c | 117 -------- .../Sema/attr-counted-by-late-parsed-off.c | 26 -- .../attr-counted-by-late-parsed-struct-ptrs.c | 254 ------------------ ...tr-counted-by-struct-ptrs-sizeless-types.c | 17 -- clang/test/Sema/attr-counted-by-struct-ptrs.c | 224 --------------- .../Sema/attr-counted-by-vla-sizeless-types.c | 11 - clang/test/Sema/attr-counted-by-vla.c | 193 ------------- clang/test/Sema/attr-counted-by.c | 112 ++++++++ 21 files changed, 148 insertions(+), 1117 deletions(-) delete mode 100644 clang/test/AST/attr-counted-by-late-parsed-struct-ptrs.c delete mode 100644 clang/test/AST/attr-counted-by-struct-ptrs.c delete mode 100644 clang/test/Sema/attr-counted-by-late-parsed-off.c delete mode 100644 clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs.c delete mode 100644 clang/test/Sema/attr-counted-by-struct-ptrs-sizeless-types.c delete mode 100644 clang/test/Sema/attr-counted-by-struct-ptrs.c delete mode 100644 clang/test/Sema/attr-counted-by-vla-sizeless-types.c delete mode 100644 clang/test/Sema/attr-counted-by-vla.c create mode 100644 clang/test/Sema/attr-counted-by.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2f83f5c6d54e..7af5869d2176 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -317,8 +317,7 @@ New Compiler Flags - ``-fexperimental-late-parse-attributes`` enables an experimental feature to allow late parsing certain attributes in specific contexts where they would - not normally be late parsed. Currently this allows late parsing the - `counted_by` attribute in C. See `Attribute Changes in Clang`_. + not normally be late parsed. - ``-fseparate-named-sections`` uses separate unique sections for global symbols in named special sections (i.e. symbols annotated with @@ -407,24 +406,6 @@ Attribute Changes in Clang - The ``clspv_libclc_builtin`` attribute has been added to allow clspv (`OpenCL-C to Vulkan SPIR-V compiler `_) to identify functions coming from libclc (`OpenCL-C builtin library `_). -- The ``counted_by`` attribute is now allowed on pointers that are members of a - struct in C. - -- The ``counted_by`` attribute can now be late parsed in C when - ``-fexperimental-late-parse-attributes`` is passed but only when attribute is - used in the declaration attribute position. This allows using the - attribute on existing code where it previously impossible to do so without - re-ordering struct field declarations would break ABI as shown below. - - .. code-block:: c - - struct BufferTy { - /* Refering to `count` requires late parsing */ - char* buffer __counted_by(count); - /* Swapping `buffer` and `count` to avoid late parsing would break ABI */ - size_t count; - }; - Improvements to Clang's diagnostics ----------------------------------- diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index c7a8e785913b..da3834f19ca0 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2515,7 +2515,6 @@ public: bool isRecordType() const; bool isClassType() const; bool isStructureType() const; - bool isStructureTypeWithFlexibleArrayMember() const; bool isObjCBoxableRecordType() const; bool isInterfaceType() const; bool isStructureOrClassType() const; diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 7a7721239a28..38ee8356583b 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2229,8 +2229,7 @@ def TypeNullUnspecified : TypeAttr { def CountedBy : DeclOrTypeAttr { let Spellings = [Clang<"counted_by">]; let Subjects = SubjectList<[Field], ErrorDiag>; - let Args = [ExprArgument<"Count">, IntArgument<"NestedLevel", 1>]; - let LateParsed = LateAttrParseExperimentalExt; + let Args = [ExprArgument<"Count">, IntArgument<"NestedLevel">]; let ParseArgumentsAsUnevaluated = 1; let Documentation = [CountedByDocs]; let LangOpts = [COnly]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8e6596410c5d..09b1874f9fdd 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6533,10 +6533,8 @@ def warn_superclass_variable_sized_type_not_at_end : Warning< def err_flexible_array_count_not_in_same_struct : Error< "'counted_by' field %0 isn't within the same struct as the flexible array">; -def err_counted_by_attr_not_on_ptr_or_flexible_array_member : Error< - "'counted_by' only applies to pointers or C99 flexible array members">; -def err_counted_by_attr_on_array_not_flexible_array_member : Error< - "'counted_by' on arrays only applies to C99 flexible array members">; +def err_counted_by_attr_not_on_flexible_array_member : Error< + "'counted_by' only applies to C99 flexible array members">; def err_counted_by_attr_refer_to_itself : Error< "'counted_by' cannot refer to the flexible array member %0">; def err_counted_by_must_be_in_structure : Error< @@ -6551,17 +6549,6 @@ def err_counted_by_attr_refer_to_union : Error< "'counted_by' argument cannot refer to a union member">; def note_flexible_array_counted_by_attr_field : Note< "field %0 declared here">; -def err_counted_by_attr_pointee_unknown_size : Error< - "'counted_by' cannot be applied to %select{" - "a pointer with pointee|" // pointer - "an array with element}0" // array - " of unknown size because %1 is %select{" - "an incomplete type|" // CountedByInvalidPointeeTypeKind::INCOMPLETE - "a sizeless type|" // CountedByInvalidPointeeTypeKind::SIZELESS - "a function type|" // CountedByInvalidPointeeTypeKind::FUNCTION - // CountedByInvalidPointeeTypeKind::FLEXIBLE_ARRAY_MEMBER - "a struct type with a flexible array member" - "}2">; let CategoryName = "ARC Semantic Issue" in { diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index af50164a8f93..1e796e828b10 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1645,8 +1645,6 @@ private: bool EnterScope, bool OnDefinition); void ParseLexedAttribute(LateParsedAttribute &LA, bool EnterScope, bool OnDefinition); - void ParseLexedCAttribute(LateParsedAttribute &LA, - ParsedAttributes *OutAttrs = nullptr); void ParseLexedMethodDeclarations(ParsingClass &Class); void ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM); void ParseLexedMethodDefs(ParsingClass &Class); @@ -2533,8 +2531,7 @@ private: void ParseStructDeclaration( ParsingDeclSpec &DS, - llvm::function_ref FieldsCallback, - LateParsedAttrList *LateFieldAttrs = nullptr); + llvm::function_ref FieldsCallback); DeclGroupPtrTy ParseTopLevelStmtDecl(); @@ -3112,8 +3109,6 @@ private: SourceLocation ScopeLoc, ParsedAttr::Form Form); - void DistributeCLateParsedAttrs(Decl *Dcl, LateParsedAttrList *LateAttrs); - void ParseBoundsAttribute(IdentifierInfo &AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d4d4a82525a0..b16a304960d3 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11396,8 +11396,7 @@ public: QualType BuildMatrixType(QualType T, Expr *NumRows, Expr *NumColumns, SourceLocation AttrLoc); - QualType BuildCountAttributedArrayOrPointerType(QualType WrappedTy, - Expr *CountExpr); + QualType BuildCountAttributedArrayType(QualType WrappedTy, Expr *CountExpr); QualType BuildAddressSpaceAttr(QualType &T, LangAS ASIdx, Expr *AddrSpace, SourceLocation AttrLoc); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index f69a8f80a639..e31741cd4424 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -632,16 +632,6 @@ bool Type::isStructureType() const { return false; } -bool Type::isStructureTypeWithFlexibleArrayMember() const { - const auto *RT = getAs(); - if (!RT) - return false; - const auto *Decl = RT->getDecl(); - if (!Decl->isStruct()) - return false; - return Decl->hasFlexibleArrayMember(); -} - bool Type::isObjCBoxableRecordType() const { if (const auto *RT = getAs()) return RT->getDecl()->hasAttr(); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 8405b44685ae..2ce8fa98089f 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3288,19 +3288,6 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs, } } -void Parser::DistributeCLateParsedAttrs(Decl *Dcl, - LateParsedAttrList *LateAttrs) { - assert(Dcl && "Dcl cannot be null"); - - if (!LateAttrs) - return; - - for (auto *LateAttr : *LateAttrs) { - if (LateAttr->Decls.empty()) - LateAttr->addDecl(Dcl); - } -} - /// Bounds attributes (e.g., counted_by): /// AttrName '(' expression ')' void Parser::ParseBoundsAttribute(IdentifierInfo &AttrName, @@ -4838,14 +4825,13 @@ static void DiagnoseCountAttributedTypeInUnnamedAnon(ParsingDeclSpec &DS, /// void Parser::ParseStructDeclaration( ParsingDeclSpec &DS, - llvm::function_ref FieldsCallback, - LateParsedAttrList *LateFieldAttrs) { + llvm::function_ref FieldsCallback) { if (Tok.is(tok::kw___extension__)) { // __extension__ silences extension warnings in the subexpression. ExtensionRAIIObject O(Diags); // Use RAII to do this. ConsumeToken(); - return ParseStructDeclaration(DS, FieldsCallback, LateFieldAttrs); + return ParseStructDeclaration(DS, FieldsCallback); } // Parse leading attributes. @@ -4910,12 +4896,10 @@ void Parser::ParseStructDeclaration( } // If attributes exist after the declarator, parse them. - MaybeParseGNUAttributes(DeclaratorInfo.D, LateFieldAttrs); + MaybeParseGNUAttributes(DeclaratorInfo.D); // We're done with this declarator; invoke the callback. - Decl *Field = FieldsCallback(DeclaratorInfo); - if (Field) - DistributeCLateParsedAttrs(Field, LateFieldAttrs); + FieldsCallback(DeclaratorInfo); // If we don't have a comma, it is either the end of the list (a ';') // or an error, bail out. @@ -4926,69 +4910,6 @@ void Parser::ParseStructDeclaration( } } -/// Finish parsing an attribute for which parsing was delayed. -/// This will be called at the end of parsing a class declaration -/// for each LateParsedAttribute. We consume the saved tokens and -/// create an attribute with the arguments filled in. We add this -/// to the Attribute list for the decl. -void Parser::ParseLexedCAttribute(LateParsedAttribute &LA, - ParsedAttributes *OutAttrs) { - // Create a fake EOF so that attribute parsing won't go off the end of the - // attribute. - Token AttrEnd; - AttrEnd.startToken(); - AttrEnd.setKind(tok::eof); - AttrEnd.setLocation(Tok.getLocation()); - AttrEnd.setEofData(LA.Toks.data()); - LA.Toks.push_back(AttrEnd); - - // Append the current token at the end of the new token stream so that it - // doesn't get lost. - LA.Toks.push_back(Tok); - PP.EnterTokenStream(LA.Toks, /*DisableMacroExpansion=*/true, - /*IsReinject=*/true); - // Drop the current token and bring the first cached one. It's the same token - // as when we entered this function. - ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); - - ParsedAttributes Attrs(AttrFactory); - - assert(LA.Decls.size() <= 1 && - "late field attribute expects to have at most one declaration."); - - // Dispatch based on the attribute and parse it - const AttributeCommonInfo::Form ParsedForm = ParsedAttr::Form::GNU(); - IdentifierInfo *ScopeName = nullptr; - const ParsedAttr::Kind AttrKind = - ParsedAttr::getParsedKind(&LA.AttrName, /*ScopeName=*/ScopeName, - /*SyntaxUsed=*/ParsedForm.getSyntax()); - switch (AttrKind) { - case ParsedAttr::Kind::AT_CountedBy: - ParseBoundsAttribute(LA.AttrName, LA.AttrNameLoc, Attrs, - /*ScopeName=*/ScopeName, SourceLocation(), - /*Form=*/ParsedForm); - break; - default: - llvm_unreachable("Unhandled late parsed attribute"); - } - - for (auto *D : LA.Decls) - Actions.ActOnFinishDelayedAttribute(getCurScope(), D, Attrs); - - // Due to a parsing error, we either went over the cached tokens or - // there are still cached tokens left, so we skip the leftover tokens. - while (Tok.isNot(tok::eof)) - ConsumeAnyToken(); - - // Consume the fake EOF token if it's there - if (Tok.is(tok::eof) && Tok.getEofData() == AttrEnd.getEofData()) - ConsumeAnyToken(); - - if (OutAttrs) { - OutAttrs->takeAllFrom(Attrs); - } -} - /// ParseStructUnionBody /// struct-contents: /// struct-declaration-list @@ -5012,11 +4933,6 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope); Actions.ActOnTagStartDefinition(getCurScope(), TagDecl); - // `LateAttrParseExperimentalExtOnly=true` requests that only attributes - // marked with `LateAttrParseExperimentalExt` are late parsed. - LateParsedAttrList LateFieldAttrs(/*PSoon=*/false, - /*LateAttrParseExperimentalExtOnly=*/true); - // While we still have something to read, read the declarations in the struct. while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { @@ -5067,19 +4983,18 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, } if (!Tok.is(tok::at)) { - auto CFieldCallback = [&](ParsingFieldDeclarator &FD) -> Decl * { + auto CFieldCallback = [&](ParsingFieldDeclarator &FD) { // Install the declarator into the current TagDecl. Decl *Field = Actions.ActOnField(getCurScope(), TagDecl, FD.D.getDeclSpec().getSourceRange().getBegin(), FD.D, FD.BitfieldSize); FD.complete(Field); - return Field; }; // Parse all the comma separated declarators. ParsingDeclSpec DS(*this); - ParseStructDeclaration(DS, CFieldCallback, &LateFieldAttrs); + ParseStructDeclaration(DS, CFieldCallback); } else { // Handle @defs ConsumeToken(); if (!Tok.isObjCAtKeyword(tok::objc_defs)) { @@ -5120,12 +5035,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, ParsedAttributes attrs(AttrFactory); // If attributes exist after struct contents, parse them. - MaybeParseGNUAttributes(attrs, &LateFieldAttrs); - - // Late parse field attributes if necessary. - assert(!getLangOpts().CPlusPlus); - for (auto *LateAttr : LateFieldAttrs) - ParseLexedCAttribute(*LateAttr); + MaybeParseGNUAttributes(attrs); SmallVector FieldDecls(TagDecl->fields()); diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 6a2088a73c55..89f4acbd25e4 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -780,16 +780,16 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, } bool addedToDeclSpec = false; - auto ObjCPropertyCallback = [&](ParsingFieldDeclarator &FD) -> Decl * { + auto ObjCPropertyCallback = [&](ParsingFieldDeclarator &FD) { if (FD.D.getIdentifier() == nullptr) { Diag(AtLoc, diag::err_objc_property_requires_field_name) << FD.D.getSourceRange(); - return nullptr; + return; } if (FD.BitfieldSize) { Diag(AtLoc, diag::err_objc_property_bitfield) << FD.D.getSourceRange(); - return nullptr; + return; } // Map a nullability property attribute to a context-sensitive keyword @@ -818,7 +818,6 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, MethodImplKind); FD.complete(Property); - return Property; }; // Parse all the comma separated declarators. @@ -2014,7 +2013,7 @@ void Parser::ParseObjCClassInstanceVariables(ObjCContainerDecl *interfaceDecl, continue; } - auto ObjCIvarCallback = [&](ParsingFieldDeclarator &FD) -> Decl * { + auto ObjCIvarCallback = [&](ParsingFieldDeclarator &FD) { assert(getObjCDeclContext() == interfaceDecl && "Ivar should have interfaceDecl as its decl context"); // Install the declarator into the interface decl. @@ -2025,7 +2024,6 @@ void Parser::ParseObjCClassInstanceVariables(ObjCContainerDecl *interfaceDecl, if (Field) AllIvarDecls.push_back(Field); FD.complete(Field); - return Field; }; // Parse all the comma separated declarators. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index c8b71631076b..30776ff537fb 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -8633,82 +8633,31 @@ static const RecordDecl *GetEnclosingNamedOrTopAnonRecord(const FieldDecl *FD) { return RD; } -enum class CountedByInvalidPointeeTypeKind { - INCOMPLETE, - SIZELESS, - FUNCTION, - FLEXIBLE_ARRAY_MEMBER, - VALID, -}; - -static bool CheckCountedByAttrOnField( - Sema &S, FieldDecl *FD, Expr *E, - llvm::SmallVectorImpl &Decls) { - // Check the context the attribute is used in - +static bool +CheckCountExpr(Sema &S, FieldDecl *FD, Expr *E, + llvm::SmallVectorImpl &Decls) { if (FD->getParent()->isUnion()) { S.Diag(FD->getBeginLoc(), diag::err_counted_by_attr_in_union) << FD->getSourceRange(); return true; } - const auto FieldTy = FD->getType(); - if (!FieldTy->isArrayType() && !FieldTy->isPointerType()) { - S.Diag(FD->getBeginLoc(), - diag::err_counted_by_attr_not_on_ptr_or_flexible_array_member) - << FD->getLocation(); + if (!E->getType()->isIntegerType() || E->getType()->isBooleanType()) { + S.Diag(E->getBeginLoc(), diag::err_counted_by_attr_argument_not_integer) + << E->getSourceRange(); return true; } LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = LangOptions::StrictFlexArraysLevelKind::IncompleteOnly; - if (FieldTy->isArrayType() && - !Decl::isFlexibleArrayMemberLike(S.getASTContext(), FD, FieldTy, - StrictFlexArraysLevel, true)) { - S.Diag(FD->getBeginLoc(), - diag::err_counted_by_attr_on_array_not_flexible_array_member) - << FD->getLocation(); - return true; - } - CountedByInvalidPointeeTypeKind InvalidTypeKind = - CountedByInvalidPointeeTypeKind::VALID; - QualType PointeeTy; - int SelectPtrOrArr = 0; - if (FieldTy->isPointerType()) { - PointeeTy = FieldTy->getPointeeType(); - SelectPtrOrArr = 0; - } else { - assert(FieldTy->isArrayType()); - const ArrayType *AT = S.getASTContext().getAsArrayType(FieldTy); - PointeeTy = AT->getElementType(); - SelectPtrOrArr = 1; - } - // Note: The `Decl::isFlexibleArrayMemberLike` check earlier on means - // only `PointeeTy->isStructureTypeWithFlexibleArrayMember()` is reachable - // when `FieldTy->isArrayType()`. - if (PointeeTy->isIncompleteType()) { - InvalidTypeKind = CountedByInvalidPointeeTypeKind::INCOMPLETE; - } else if (PointeeTy->isSizelessType()) { - InvalidTypeKind = CountedByInvalidPointeeTypeKind::SIZELESS; - } else if (PointeeTy->isFunctionType()) { - InvalidTypeKind = CountedByInvalidPointeeTypeKind::FUNCTION; - } else if (PointeeTy->isStructureTypeWithFlexibleArrayMember()) { - InvalidTypeKind = CountedByInvalidPointeeTypeKind::FLEXIBLE_ARRAY_MEMBER; - } - - if (InvalidTypeKind != CountedByInvalidPointeeTypeKind::VALID) { - S.Diag(FD->getBeginLoc(), diag::err_counted_by_attr_pointee_unknown_size) - << SelectPtrOrArr << PointeeTy << (int)InvalidTypeKind - << FD->getSourceRange(); - return true; - } - - // Check the expression - - if (!E->getType()->isIntegerType() || E->getType()->isBooleanType()) { - S.Diag(E->getBeginLoc(), diag::err_counted_by_attr_argument_not_integer) - << E->getSourceRange(); + if (!Decl::isFlexibleArrayMemberLike(S.getASTContext(), FD, FD->getType(), + StrictFlexArraysLevel, true)) { + // The "counted_by" attribute must be on a flexible array member. + SourceRange SR = FD->getLocation(); + S.Diag(SR.getBegin(), + diag::err_counted_by_attr_not_on_flexible_array_member) + << SR; return true; } @@ -8771,11 +8720,10 @@ static void handleCountedByAttrField(Sema &S, Decl *D, const ParsedAttr &AL) { return; llvm::SmallVector Decls; - if (CheckCountedByAttrOnField(S, FD, CountExpr, Decls)) + if (CheckCountExpr(S, FD, CountExpr, Decls)) return; - QualType CAT = - S.BuildCountAttributedArrayOrPointerType(FD->getType(), CountExpr); + QualType CAT = S.BuildCountAttributedArrayType(FD->getType(), CountExpr); FD->setType(CAT); } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index ef0b6b701a52..c19c8cc34dd3 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -9345,9 +9345,9 @@ BuildTypeCoupledDecls(Expr *E, Decls.push_back(TypeCoupledDeclRefInfo(CountDecl, /*IsDref*/ false)); } -QualType Sema::BuildCountAttributedArrayOrPointerType(QualType WrappedTy, - Expr *CountExpr) { - assert(WrappedTy->isIncompleteArrayType() || WrappedTy->isPointerType()); +QualType Sema::BuildCountAttributedArrayType(QualType WrappedTy, + Expr *CountExpr) { + assert(WrappedTy->isIncompleteArrayType()); llvm::SmallVector Decls; BuildTypeCoupledDecls(CountExpr, Decls); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 29444f0edc2a..b10e5ba65eb1 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -7344,7 +7344,7 @@ QualType TreeTransform::TransformCountAttributedType( if (getDerived().AlwaysRebuild() || InnerTy != OldTy->desugar() || OldCount != NewCount) { // Currently, CountAttributedType can only wrap incomplete array types. - Result = SemaRef.BuildCountAttributedArrayOrPointerType(InnerTy, NewCount); + Result = SemaRef.BuildCountAttributedArrayType(InnerTy, NewCount); } TLB.push(Result); diff --git a/clang/test/AST/attr-counted-by-late-parsed-struct-ptrs.c b/clang/test/AST/attr-counted-by-late-parsed-struct-ptrs.c deleted file mode 100644 index a585a45eeff0..000000000000 --- a/clang/test/AST/attr-counted-by-late-parsed-struct-ptrs.c +++ /dev/null @@ -1,45 +0,0 @@ -// RUN: %clang_cc1 -fexperimental-late-parse-attributes %s -ast-dump | FileCheck %s - -#define __counted_by(f) __attribute__((counted_by(f))) - -struct size_known { - int field; -}; - -//============================================================================== -// __counted_by on struct member pointer in decl attribute position -//============================================================================== - -struct on_member_pointer_complete_ty { - struct size_known *buf __counted_by(count); - int count; -}; -// CHECK-LABEL: struct on_member_pointer_complete_ty definition -// CHECK-NEXT: |-FieldDecl {{.*}} buf 'struct size_known * __counted_by(count)':'struct size_known *' -// CHECK-NEXT: `-FieldDecl {{.*}} referenced count 'int' - -struct on_pointer_anon_count { - struct size_known *buf __counted_by(count); - struct { - int count; - }; -}; - -// CHECK-LABEL: struct on_pointer_anon_count definition -// CHECK-NEXT: |-FieldDecl {{.*}} buf 'struct size_known * __counted_by(count)':'struct size_known *' -// CHECK-NEXT: |-RecordDecl {{.*}} struct definition -// CHECK-NEXT: | `-FieldDecl {{.*}} count 'int' -// CHECK-NEXT: |-FieldDecl {{.*}} implicit 'struct on_pointer_anon_count::(anonymous at {{.*}})' -// CHECK-NEXT: `-IndirectFieldDecl {{.*}} implicit referenced count 'int' -// CHECK-NEXT: |-Field {{.*}} '' 'struct on_pointer_anon_count::(anonymous at {{.*}})' -// CHECK-NEXT: `-Field {{.*}} 'count' 'int' - -//============================================================================== -// __counted_by on struct member pointer in type attribute position -//============================================================================== -// TODO: Correctly parse counted_by as a type attribute. Currently it is parsed -// as a declaration attribute and is **not** late parsed resulting in the `count` -// field being unavailable. -// -// See `clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs.c` for test -// cases. diff --git a/clang/test/AST/attr-counted-by-struct-ptrs.c b/clang/test/AST/attr-counted-by-struct-ptrs.c deleted file mode 100644 index 79a453d239cd..000000000000 --- a/clang/test/AST/attr-counted-by-struct-ptrs.c +++ /dev/null @@ -1,117 +0,0 @@ -// RUN: %clang_cc1 %s -ast-dump | FileCheck %s - -#define __counted_by(f) __attribute__((counted_by(f))) - -struct size_unknown; -struct size_known { - int field; -}; - -//============================================================================== -// __counted_by on struct member pointer in decl attribute position -//============================================================================== - -// CHECK-LABEL: RecordDecl {{.+}} struct on_member_pointer_complete_ty definition -// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int' -// CHECK-NEXT: `-FieldDecl {{.+}} buf 'struct size_known * __counted_by(count)':'struct size_known *' -struct on_member_pointer_complete_ty { - int count; - struct size_known * buf __counted_by(count); -}; - -// CHECK-LABEL: RecordDecl {{.+}} struct on_pointer_anon_buf definition -// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int' -// CHECK-NEXT: |-RecordDecl {{.+}} struct definition -// CHECK-NEXT: | `-FieldDecl {{.+}} buf 'struct size_known * __counted_by(count)':'struct size_known *' -// CHECK-NEXT: |-FieldDecl {{.+}} implicit 'struct on_pointer_anon_buf::(anonymous at [[ANON_STRUCT_PATH:.+]])' -// CHECK-NEXT: `-IndirectFieldDecl {{.+}} implicit buf 'struct size_known * __counted_by(count)':'struct size_known *' -// CHECK-NEXT: |-Field {{.+}} '' 'struct on_pointer_anon_buf::(anonymous at [[ANON_STRUCT_PATH]])' -// CHECK-NEXT: `-Field {{.+}} 'buf' 'struct size_known * __counted_by(count)':'struct size_known *' -struct on_pointer_anon_buf { - int count; - struct { - struct size_known *buf __counted_by(count); - }; -}; - -struct on_pointer_anon_count { - struct { - int count; - }; - struct size_known *buf __counted_by(count); -}; - -//============================================================================== -// __counted_by on struct member pointer in type attribute position -//============================================================================== -// TODO: Correctly parse counted_by as a type attribute. Currently it is parsed -// as a declaration attribute - -// CHECK-LABEL: RecordDecl {{.+}} struct on_member_pointer_complete_ty_ty_pos definition -// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int' -// CHECK-NEXT: `-FieldDecl {{.+}} buf 'struct size_known * __counted_by(count)':'struct size_known *' -struct on_member_pointer_complete_ty_ty_pos { - int count; - struct size_known *__counted_by(count) buf; -}; - -// TODO: This should be forbidden but isn't due to counted_by being treated as a -// declaration attribute. The attribute ends up on the outer most pointer -// (allowed by sema) even though syntactically its supposed to be on the inner -// pointer (would not allowed by sema due to pointee being a function type). -// CHECK-LABEL: RecordDecl {{.+}} struct on_member_pointer_fn_ptr_ty_ty_pos_inner definition -// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int' -// CHECK-NEXT: `-FieldDecl {{.+}} fn_ptr 'void (** __counted_by(count))(void)':'void (**)(void)' -struct on_member_pointer_fn_ptr_ty_ty_pos_inner { - int count; - void (* __counted_by(count) * fn_ptr)(void); -}; - -// FIXME: The generated AST here is wrong. The attribute should be on the inner -// pointer. -// CHECK-LABEL: RecordDecl {{.+}} struct on_nested_pointer_inner definition -// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int' -// CHECK-NEXT: `-FieldDecl {{.+}} buf 'struct size_known ** __counted_by(count)':'struct size_known **' -struct on_nested_pointer_inner { - int count; - // TODO: This should be disallowed because in the `-fbounds-safety` model - // `__counted_by` can only be nested when used in function parameters. - struct size_known *__counted_by(count) *buf; -}; - -// CHECK-LABEL: RecordDecl {{.+}} struct on_nested_pointer_outer definition -// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int' -// CHECK-NEXT: `-FieldDecl {{.+}} buf 'struct size_known ** __counted_by(count)':'struct size_known **' -struct on_nested_pointer_outer { - int count; - struct size_known **__counted_by(count) buf; -}; - -// CHECK-LABEL: RecordDecl {{.+}} struct on_pointer_anon_buf_ty_pos definition -// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int' -// CHECK-NEXT: |-RecordDecl {{.+}} struct definition -// CHECK-NEXT: | `-FieldDecl {{.+}} buf 'struct size_known * __counted_by(count)':'struct size_known *' -// CHECK-NEXT: |-FieldDecl {{.+}} implicit 'struct on_pointer_anon_buf_ty_pos::(anonymous at [[ANON_STRUCT_PATH2:.+]])' -// CHECK-NEXT: `-IndirectFieldDecl {{.+}} implicit buf 'struct size_known * __counted_by(count)':'struct size_known *' -// CHECK-NEXT: |-Field {{.+}} '' 'struct on_pointer_anon_buf_ty_pos::(anonymous at [[ANON_STRUCT_PATH2]])' -// CHECK-NEXT: `-Field {{.+}} 'buf' 'struct size_known * __counted_by(count)':'struct size_known *' -struct on_pointer_anon_buf_ty_pos { - int count; - struct { - struct size_known * __counted_by(count) buf; - }; -}; - -// CHECK-LABEL: RecordDecl {{.+}} struct on_pointer_anon_count_ty_pos definition -// CHECK-NEXT: |-RecordDecl {{.+}} struct definition -// CHECK-NEXT: | `-FieldDecl {{.+}} count 'int' -// CHECK-NEXT: |-FieldDecl {{.+}} implicit 'struct on_pointer_anon_count_ty_pos::(anonymous at [[ANON_STRUCT_PATH3:.+]])' -// CHECK-NEXT: |-IndirectFieldDecl {{.+}} implicit referenced count 'int' -// CHECK-NEXT: | |-Field {{.+}} '' 'struct on_pointer_anon_count_ty_pos::(anonymous at [[ANON_STRUCT_PATH3]])' -// CHECK-NEXT: | `-Field {{.+}} 'count' 'int' -struct on_pointer_anon_count_ty_pos { - struct { - int count; - }; - struct size_known *__counted_by(count) buf; -}; diff --git a/clang/test/Sema/attr-counted-by-late-parsed-off.c b/clang/test/Sema/attr-counted-by-late-parsed-off.c deleted file mode 100644 index 34f51d10c083..000000000000 --- a/clang/test/Sema/attr-counted-by-late-parsed-off.c +++ /dev/null @@ -1,26 +0,0 @@ -// RUN: %clang_cc1 -DNEEDS_LATE_PARSING -fno-experimental-late-parse-attributes -fsyntax-only -verify %s -// RUN: %clang_cc1 -DNEEDS_LATE_PARSING -fsyntax-only -verify %s - -// RUN: %clang_cc1 -UNEEDS_LATE_PARSING -fno-experimental-late-parse-attributes -fsyntax-only -verify=ok %s -// RUN: %clang_cc1 -UNEEDS_LATE_PARSING -fsyntax-only -verify=ok %s - -#define __counted_by(f) __attribute__((counted_by(f))) - -struct size_known { int dummy; }; - -#ifdef NEEDS_LATE_PARSING -struct on_decl { - // expected-error@+1{{use of undeclared identifier 'count'}} - struct size_known *buf __counted_by(count); - int count; -}; - -#else - -// ok-no-diagnostics -struct on_decl { - int count; - struct size_known *buf __counted_by(count); -}; - -#endif diff --git a/clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs.c b/clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs.c deleted file mode 100644 index 9ff3b080f657..000000000000 --- a/clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs.c +++ /dev/null @@ -1,254 +0,0 @@ -// RUN: %clang_cc1 -fexperimental-late-parse-attributes -fsyntax-only -verify %s - -#define __counted_by(f) __attribute__((counted_by(f))) - -struct size_unknown; -struct size_known { - int field; -}; - -typedef void(*fn_ptr_ty)(void); - -//============================================================================== -// __counted_by on struct member pointer in decl attribute position -//============================================================================== - -struct on_member_pointer_complete_ty { - struct size_known * buf __counted_by(count); - int count; -}; - -struct on_member_pointer_incomplete_ty { - struct size_unknown * buf __counted_by(count); // expected-error{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct size_unknown' is an incomplete type}} - int count; -}; - -struct on_member_pointer_const_incomplete_ty { - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'const struct size_unknown' is an incomplete type}} - const struct size_unknown * buf __counted_by(count); - int count; -}; - -struct on_member_pointer_void_ty { - void* buf __counted_by(count); // expected-error{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void' is an incomplete type}} - int count; -}; - -struct on_member_pointer_fn_ptr_ty { - // buffer of `count` function pointers is allowed - void (**fn_ptr)(void) __counted_by(count); - int count; -}; - - -struct on_member_pointer_fn_ptr_ty_ptr_ty { - // buffer of `count` function pointers is allowed - fn_ptr_ty* fn_ptr __counted_by(count); - int count; -}; - -struct on_member_pointer_fn_ty { - // buffer of `count` functions is not allowed - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}} - void (*fn_ptr)(void) __counted_by(count); - int count; -}; - -struct on_member_pointer_fn_ptr_ty_ty { - // buffer of `count` functions is not allowed - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}} - fn_ptr_ty fn_ptr __counted_by(count); - int count; -}; - -struct has_unannotated_vla { - int count; - int buffer[]; -}; - -struct on_member_pointer_struct_with_vla { - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}} - struct has_unannotated_vla* objects __counted_by(count); - int count; -}; - -struct has_annotated_vla { - int count; - int buffer[] __counted_by(count); -}; - -// Currently prevented because computing the size of `objects` at runtime would -// require an O(N) walk of `objects` to take into account the length of the VLA -// in each struct instance. -struct on_member_pointer_struct_with_annotated_vla { - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}} - struct has_annotated_vla* objects __counted_by(count); - int count; -}; - -struct on_pointer_anon_buf { - // TODO: Support referring to parent scope - struct { - // expected-error@+1{{use of undeclared identifier 'count'}} - struct size_known *buf __counted_by(count); - }; - int count; -}; - -struct on_pointer_anon_count { - struct size_known *buf __counted_by(count); - struct { - int count; - }; -}; - -//============================================================================== -// __counted_by on struct member pointer in type attribute position -//============================================================================== -// TODO: Correctly parse counted_by as a type attribute. Currently it is parsed -// as a declaration attribute and is **not** late parsed resulting in the `count` -// field being unavailable. - -struct on_member_pointer_complete_ty_ty_pos { - // TODO: Allow this - // expected-error@+1{{use of undeclared identifier 'count'}} - struct size_known *__counted_by(count) buf; - int count; -}; - -struct on_member_pointer_incomplete_ty_ty_pos { - // TODO: Allow this - // expected-error@+1{{use of undeclared identifier 'count'}} - struct size_unknown * __counted_by(count) buf; - int count; -}; - -struct on_member_pointer_const_incomplete_ty_ty_pos { - // TODO: Allow this - // expected-error@+1{{use of undeclared identifier 'count'}} - const struct size_unknown * __counted_by(count) buf; - int count; -}; - -struct on_member_pointer_void_ty_ty_pos { - // TODO: This should fail because the attribute is - // on a pointer with the pointee being an incomplete type. - // expected-error@+1{{use of undeclared identifier 'count'}} - void *__counted_by(count) buf; - int count; -}; - -// - - -struct on_member_pointer_fn_ptr_ty_pos { - // TODO: buffer of `count` function pointers should be allowed - // but fails because this isn't late parsed. - // expected-error@+1{{use of undeclared identifier 'count'}} - void (** __counted_by(count) fn_ptr)(void); - int count; -}; - -struct on_member_pointer_fn_ptr_ty_ptr_ty_pos { - // TODO: buffer of `count` function pointers should be allowed - // but fails because this isn't late parsed. - // expected-error@+1{{use of undeclared identifier 'count'}} - fn_ptr_ty* __counted_by(count) fn_ptr; - int count; -}; - -struct on_member_pointer_fn_ty_ty_pos { - // TODO: This should fail because the attribute is - // on a pointer with the pointee being a function type. - // expected-error@+1{{use of undeclared identifier 'count'}} - void (* __counted_by(count) fn_ptr)(void); - int count; -}; - -struct on_member_pointer_fn_ptr_ty_ty_pos { - // TODO: buffer of `count` function pointers should be allowed - // expected-error@+1{{use of undeclared identifier 'count'}} - void (** __counted_by(count) fn_ptr)(void); - int count; -}; - -struct on_member_pointer_fn_ptr_ty_typedef_ty_pos { - // TODO: This should fail because the attribute is - // on a pointer with the pointee being a function type. - // expected-error@+1{{use of undeclared identifier 'count'}} - fn_ptr_ty __counted_by(count) fn_ptr; - int count; -}; - -struct on_member_pointer_fn_ptr_ty_ty_pos_inner { - // TODO: This should fail because the attribute is - // on a pointer with the pointee being a function type. - // expected-error@+1{{use of undeclared identifier 'count'}} - void (* __counted_by(count) * fn_ptr)(void); - int count; -}; - -struct on_member_pointer_struct_with_vla_ty_pos { - // TODO: This should fail because the attribute is - // on a pointer with the pointee being a struct type with a VLA. - // expected-error@+1{{use of undeclared identifier 'count'}} - struct has_unannotated_vla *__counted_by(count) objects; - int count; -}; - -struct on_member_pointer_struct_with_annotated_vla_ty_pos { - // TODO: This should fail because the attribute is - // on a pointer with the pointee being a struct type with a VLA. - // expected-error@+1{{use of undeclared identifier 'count'}} - struct has_annotated_vla* __counted_by(count) objects; - int count; -}; - -struct on_nested_pointer_inner { - // TODO: This should be disallowed because in the `-fbounds-safety` model - // `__counted_by` can only be nested when used in function parameters. - // expected-error@+1{{use of undeclared identifier 'count'}} - struct size_known *__counted_by(count) *buf; - int count; -}; - -struct on_nested_pointer_outer { - // TODO: Allow this - // expected-error@+1{{use of undeclared identifier 'count'}} - struct size_known **__counted_by(count) buf; - int count; -}; - -struct on_pointer_anon_buf_ty_pos { - struct { - // TODO: Support referring to parent scope - // expected-error@+1{{use of undeclared identifier 'count'}} - struct size_known * __counted_by(count) buf; - }; - int count; -}; - -struct on_pointer_anon_count_ty_pos { - // TODO: Allow this - // expected-error@+1{{use of undeclared identifier 'count'}} - struct size_known *__counted_by(count) buf; - struct { - int count; - }; -}; - -//============================================================================== -// __counted_by on struct non-pointer members -//============================================================================== - -struct on_pod_ty { - // expected-error@+1{{'counted_by' only applies to pointers or C99 flexible array members}} - int wrong_ty __counted_by(count); - int count; -}; - -struct on_void_ty { - // expected-error@+2{{'counted_by' only applies to pointers or C99 flexible array members}} - // expected-error@+1{{field has incomplete type 'void'}} - void wrong_ty __counted_by(count); - int count; -}; diff --git a/clang/test/Sema/attr-counted-by-struct-ptrs-sizeless-types.c b/clang/test/Sema/attr-counted-by-struct-ptrs-sizeless-types.c deleted file mode 100644 index 9b0f2eafb13c..000000000000 --- a/clang/test/Sema/attr-counted-by-struct-ptrs-sizeless-types.c +++ /dev/null @@ -1,17 +0,0 @@ -// __SVInt8_t is specific to ARM64 so specify that in the target triple -// RUN: %clang_cc1 -triple arm64-apple-darwin -fsyntax-only -verify %s - -#define __counted_by(f) __attribute__((counted_by(f))) - -struct on_sizeless_pointee_ty { - int count; - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because '__SVInt8_t' is a sizeless type}} - __SVInt8_t* member __counted_by(count); -}; - -struct on_sizeless_ty { - int count; - // expected-error@+2{{'counted_by' only applies to pointers or C99 flexible array members}} - // expected-error@+1{{field has sizeless type '__SVInt8_t'}} - __SVInt8_t member __counted_by(count); -}; diff --git a/clang/test/Sema/attr-counted-by-struct-ptrs.c b/clang/test/Sema/attr-counted-by-struct-ptrs.c deleted file mode 100644 index cd2bfe36938b..000000000000 --- a/clang/test/Sema/attr-counted-by-struct-ptrs.c +++ /dev/null @@ -1,224 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -#define __counted_by(f) __attribute__((counted_by(f))) - -struct size_unknown; -struct size_known { - int field; -}; - -typedef void(*fn_ptr_ty)(void); - -//============================================================================== -// __counted_by on struct member pointer in decl attribute position -//============================================================================== - -struct on_member_pointer_complete_ty { - int count; - struct size_known * buf __counted_by(count); -}; - -struct on_member_pointer_incomplete_ty { - int count; - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct size_unknown' is an incomplete type}} - struct size_unknown * buf __counted_by(count); -}; - -struct on_member_pointer_const_incomplete_ty { - int count; - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'const struct size_unknown' is an incomplete type}} - const struct size_unknown * buf __counted_by(count); -}; - -struct on_member_pointer_void_ty { - int count; - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void' is an incomplete type}} - void* buf __counted_by(count); -}; - -struct on_member_pointer_fn_ptr_ty { - int count; - // buffer of `count` function pointers is allowed - void (**fn_ptr)(void) __counted_by(count); -}; - -struct on_member_pointer_fn_ptr_ty_ptr_ty { - int count; - // buffer of `count` function pointers is allowed - fn_ptr_ty* fn_ptr __counted_by(count); -}; - -struct on_member_pointer_fn_ty { - int count; - // buffer of `count` functions is not allowed - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}} - void (*fn_ptr)(void) __counted_by(count); -}; - -struct on_member_pointer_fn_ptr_ty_ty { - int count; - // buffer of `count` functions is not allowed - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}} - fn_ptr_ty fn_ptr __counted_by(count); -}; - -struct has_unannotated_vla { - int count; - int buffer[]; -}; - -struct on_member_pointer_struct_with_vla { - int count; - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}} - struct has_unannotated_vla* objects __counted_by(count); -}; - -struct has_annotated_vla { - int count; - int buffer[] __counted_by(count); -}; - -// Currently prevented because computing the size of `objects` at runtime would -// require an O(N) walk of `objects` to take into account the length of the VLA -// in each struct instance. -struct on_member_pointer_struct_with_annotated_vla { - int count; - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}} - struct has_annotated_vla* objects __counted_by(count); -}; - -struct on_pointer_anon_buf { - int count; - struct { - struct size_known *buf __counted_by(count); - }; -}; - -struct on_pointer_anon_count { - struct { - int count; - }; - struct size_known *buf __counted_by(count); -}; - -//============================================================================== -// __counted_by on struct member pointer in type attribute position -//============================================================================== -// TODO: Correctly parse counted_by as a type attribute. Currently it is parsed -// as a declaration attribute - -struct on_member_pointer_complete_ty_ty_pos { - int count; - struct size_known *__counted_by(count) buf; -}; - -struct on_member_pointer_incomplete_ty_ty_pos { - int count; - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct size_unknown' is an incomplete type}} - struct size_unknown * __counted_by(count) buf; -}; - -struct on_member_pointer_const_incomplete_ty_ty_pos { - int count; - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'const struct size_unknown' is an incomplete type}} - const struct size_unknown * __counted_by(count) buf; -}; - -struct on_member_pointer_void_ty_ty_pos { - int count; - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void' is an incomplete type}} - void *__counted_by(count) buf; -}; - -// - - -struct on_member_pointer_fn_ptr_ty_pos { - int count; - // buffer of `count` function pointers is allowed - void (** __counted_by(count) fn_ptr)(void); -}; - -struct on_member_pointer_fn_ptr_ty_ptr_ty_pos { - int count; - // buffer of `count` function pointers is allowed - fn_ptr_ty* __counted_by(count) fn_ptr; -}; - -struct on_member_pointer_fn_ty_ty_pos { - int count; - // buffer of `count` functions is not allowed - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}} - void (* __counted_by(count) fn_ptr)(void); -}; - -struct on_member_pointer_fn_ptr_ty_ty_pos { - int count; - // buffer of `count` functions is not allowed - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'void (void)' is a function type}} - fn_ptr_ty __counted_by(count) fn_ptr; -}; - -// TODO: This should be forbidden but isn't due to counted_by being treated -// as a declaration attribute. -struct on_member_pointer_fn_ptr_ty_ty_pos_inner { - int count; - void (* __counted_by(count) * fn_ptr)(void); -}; - -struct on_member_pointer_struct_with_vla_ty_pos { - int count; - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_unannotated_vla' is a struct type with a flexible array member}} - struct has_unannotated_vla *__counted_by(count) objects; -}; - -// Currently prevented because computing the size of `objects` at runtime would -// require an O(N) walk of `objects` to take into account the length of the VLA -// in each struct instance. -struct on_member_pointer_struct_with_annotated_vla_ty_pos { - int count; - // expected-error@+1{{counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct has_annotated_vla' is a struct type with a flexible array member}} - struct has_annotated_vla* __counted_by(count) objects; -}; - -struct on_nested_pointer_inner { - // TODO: This should be disallowed because in the `-fbounds-safety` model - // `__counted_by` can only be nested when used in function parameters. - int count; - struct size_known *__counted_by(count) *buf; -}; - -struct on_nested_pointer_outer { - int count; - struct size_known **__counted_by(count) buf; -}; - -struct on_pointer_anon_buf_ty_pos { - int count; - struct { - struct size_known * __counted_by(count) buf; - }; -}; - -struct on_pointer_anon_count_ty_pos { - struct { - int count; - }; - struct size_known *__counted_by(count) buf; -}; - -//============================================================================== -// __counted_by on struct non-pointer members -//============================================================================== - -struct on_pod_ty { - int count; - // expected-error@+1{{'counted_by' only applies to pointers or C99 flexible array members}} - int wrong_ty __counted_by(count); -}; - -struct on_void_ty { - int count; - // expected-error@+2{{'counted_by' only applies to pointers or C99 flexible array members}} - // expected-error@+1{{field has incomplete type 'void'}} - void wrong_ty __counted_by(count); -}; diff --git a/clang/test/Sema/attr-counted-by-vla-sizeless-types.c b/clang/test/Sema/attr-counted-by-vla-sizeless-types.c deleted file mode 100644 index 31c0007501c4..000000000000 --- a/clang/test/Sema/attr-counted-by-vla-sizeless-types.c +++ /dev/null @@ -1,11 +0,0 @@ -// __SVInt8_t is specific to ARM64 so specify that in the target triple -// RUN: %clang_cc1 -triple arm64-apple-darwin -fsyntax-only -verify %s - -#define __counted_by(f) __attribute__((counted_by(f))) - -struct on_sizeless_elt_ty { - int count; - // expected-error@+2{{'counted_by' only applies to pointers or C99 flexible array members}} - // expected-error@+1{{array has sizeless element type '__SVInt8_t'}} - __SVInt8_t arr[] __counted_by(count); -}; diff --git a/clang/test/Sema/attr-counted-by-vla.c b/clang/test/Sema/attr-counted-by-vla.c deleted file mode 100644 index 3de6bd55e2d8..000000000000 --- a/clang/test/Sema/attr-counted-by-vla.c +++ /dev/null @@ -1,193 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -#define __counted_by(f) __attribute__((counted_by(f))) - -struct bar; - -struct not_found { - int count; - struct bar *fam[] __counted_by(bork); // expected-error {{use of undeclared identifier 'bork'}} -}; - -struct no_found_count_not_in_substruct { - unsigned long flags; - unsigned char count; // expected-note {{'count' declared here}} - struct A { - int dummy; - int array[] __counted_by(count); // expected-error {{'counted_by' field 'count' isn't within the same struct as the flexible array}} - } a; -}; - -struct not_found_count_not_in_unnamed_substruct { - unsigned char count; // expected-note {{'count' declared here}} - struct { - int dummy; - int array[] __counted_by(count); // expected-error {{'counted_by' field 'count' isn't within the same struct as the flexible array}} - } a; -}; - -struct not_found_count_not_in_unnamed_substruct_2 { - struct { - unsigned char count; // expected-note {{'count' declared here}} - }; - struct { - int dummy; - int array[] __counted_by(count); // expected-error {{'counted_by' field 'count' isn't within the same struct as the flexible array}} - } a; -}; - -struct not_found_count_in_other_unnamed_substruct { - struct { - unsigned char count; - } a1; - - struct { - int dummy; - int array[] __counted_by(count); // expected-error {{use of undeclared identifier 'count'}} - }; -}; - -struct not_found_count_in_other_substruct { - struct _a1 { - unsigned char count; - } a1; - - struct { - int dummy; - int array[] __counted_by(count); // expected-error {{use of undeclared identifier 'count'}} - }; -}; - -struct not_found_count_in_other_substruct_2 { - struct _a2 { - unsigned char count; - } a2; - - int array[] __counted_by(count); // expected-error {{use of undeclared identifier 'count'}} -}; - -struct not_found_suggest { - int bork; - struct bar *fam[] __counted_by(blork); // expected-error {{use of undeclared identifier 'blork'}} -}; - -int global; // expected-note {{'global' declared here}} - -struct found_outside_of_struct { - int bork; - struct bar *fam[] __counted_by(global); // expected-error {{field 'global' in 'counted_by' not inside structure}} -}; - -struct self_referrential { - int bork; - struct bar *self[] __counted_by(self); // expected-error {{use of undeclared identifier 'self'}} -}; - -struct non_int_count { - double dbl_count; - struct bar *fam[] __counted_by(dbl_count); // expected-error {{'counted_by' requires a non-boolean integer type argument}} -}; - -struct array_of_ints_count { - int integers[2]; - struct bar *fam[] __counted_by(integers); // expected-error {{'counted_by' requires a non-boolean integer type argument}} -}; - -struct not_a_fam { - int count; - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct bar' is an incomplete type}} - struct bar *non_fam __counted_by(count); -}; - -struct not_a_c99_fam { - int count; - struct bar *non_c99_fam[0] __counted_by(count); // expected-error {{'counted_by' on arrays only applies to C99 flexible array members}} -}; - -struct annotated_with_anon_struct { - unsigned long flags; - struct { - unsigned char count; - int array[] __counted_by(crount); // expected-error {{use of undeclared identifier 'crount'}} - }; -}; - -//============================================================================== -// __counted_by on a struct VLA with element type that has unknown size -//============================================================================== - -struct size_unknown; // expected-note 2{{forward declaration of 'struct size_unknown'}} -struct on_member_arr_incomplete_ty_ty_pos { - int count; - // expected-error@+2{{'counted_by' only applies to pointers or C99 flexible array members}} - // expected-error@+1{{array has incomplete element type 'struct size_unknown'}} - struct size_unknown buf[] __counted_by(count); -}; - -struct on_member_arr_incomplete_const_ty_ty_pos { - int count; - // expected-error@+2{{'counted_by' only applies to pointers or C99 flexible array members}} - // expected-error@+1{{array has incomplete element type 'const struct size_unknown'}} - const struct size_unknown buf[] __counted_by(count); -}; - -struct on_member_arr_void_ty_ty_pos { - int count; - // expected-error@+2{{'counted_by' only applies to pointers or C99 flexible array members}} - // expected-error@+1{{array has incomplete element type 'void'}} - void buf[] __counted_by(count); -}; - -typedef void(fn_ty)(int); - -struct on_member_arr_fn_ptr_ty { - int count; - // An Array of function pointers is allowed - fn_ty* buf[] __counted_by(count); -}; - -struct on_member_arr_fn_ty { - int count; - // An array of functions is not allowed. - // expected-error@+2{{'counted_by' only applies to pointers or C99 flexible array members}} - // expected-error@+1{{'buf' declared as array of functions of type 'fn_ty' (aka 'void (int)')}} - fn_ty buf[] __counted_by(count); -}; - - -// `buffer_of_structs_with_unnannotated_vla`, -// `buffer_of_structs_with_annotated_vla`, and -// `buffer_of_const_structs_with_annotated_vla` are currently prevented because -// computing the size of `Arr` at runtime would require an O(N) walk of `Arr` -// elements to take into account the length of the VLA in each struct instance. - -struct has_unannotated_VLA { - int count; - char buffer[]; -}; - -struct has_annotated_VLA { - int count; - char buffer[] __counted_by(count); -}; - -struct buffer_of_structs_with_unnannotated_vla { - int count; - // expected-error@+1{{'counted_by' cannot be applied to an array with element of unknown size because 'struct has_unannotated_VLA' is a struct type with a flexible array member}} - struct has_unannotated_VLA Arr[] __counted_by(count); -}; - - -struct buffer_of_structs_with_annotated_vla { - int count; - // expected-error@+1{{'counted_by' cannot be applied to an array with element of unknown size because 'struct has_annotated_VLA' is a struct type with a flexible array member}} - struct has_annotated_VLA Arr[] __counted_by(count); -}; - -struct buffer_of_const_structs_with_annotated_vla { - int count; - // Make sure the `const` qualifier is printed when printing the element type. - // expected-error@+1{{'counted_by' cannot be applied to an array with element of unknown size because 'const struct has_annotated_VLA' is a struct type with a flexible array member}} - const struct has_annotated_VLA Arr[] __counted_by(count); -}; - diff --git a/clang/test/Sema/attr-counted-by.c b/clang/test/Sema/attr-counted-by.c new file mode 100644 index 000000000000..d5d4ebf55739 --- /dev/null +++ b/clang/test/Sema/attr-counted-by.c @@ -0,0 +1,112 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +#define __counted_by(f) __attribute__((counted_by(f))) + +struct bar; + +struct not_found { + int count; + struct bar *fam[] __counted_by(bork); // expected-error {{use of undeclared identifier 'bork'}} +}; + +struct no_found_count_not_in_substruct { + unsigned long flags; + unsigned char count; // expected-note {{'count' declared here}} + struct A { + int dummy; + int array[] __counted_by(count); // expected-error {{'counted_by' field 'count' isn't within the same struct as the flexible array}} + } a; +}; + +struct not_found_count_not_in_unnamed_substruct { + unsigned char count; // expected-note {{'count' declared here}} + struct { + int dummy; + int array[] __counted_by(count); // expected-error {{'counted_by' field 'count' isn't within the same struct as the flexible array}} + } a; +}; + +struct not_found_count_not_in_unnamed_substruct_2 { + struct { + unsigned char count; // expected-note {{'count' declared here}} + }; + struct { + int dummy; + int array[] __counted_by(count); // expected-error {{'counted_by' field 'count' isn't within the same struct as the flexible array}} + } a; +}; + +struct not_found_count_in_other_unnamed_substruct { + struct { + unsigned char count; + } a1; + + struct { + int dummy; + int array[] __counted_by(count); // expected-error {{use of undeclared identifier 'count'}} + }; +}; + +struct not_found_count_in_other_substruct { + struct _a1 { + unsigned char count; + } a1; + + struct { + int dummy; + int array[] __counted_by(count); // expected-error {{use of undeclared identifier 'count'}} + }; +}; + +struct not_found_count_in_other_substruct_2 { + struct _a2 { + unsigned char count; + } a2; + + int array[] __counted_by(count); // expected-error {{use of undeclared identifier 'count'}} +}; + +struct not_found_suggest { + int bork; + struct bar *fam[] __counted_by(blork); // expected-error {{use of undeclared identifier 'blork'}} +}; + +int global; // expected-note {{'global' declared here}} + +struct found_outside_of_struct { + int bork; + struct bar *fam[] __counted_by(global); // expected-error {{field 'global' in 'counted_by' not inside structure}} +}; + +struct self_referrential { + int bork; + struct bar *self[] __counted_by(self); // expected-error {{use of undeclared identifier 'self'}} +}; + +struct non_int_count { + double dbl_count; + struct bar *fam[] __counted_by(dbl_count); // expected-error {{'counted_by' requires a non-boolean integer type argument}} +}; + +struct array_of_ints_count { + int integers[2]; + struct bar *fam[] __counted_by(integers); // expected-error {{'counted_by' requires a non-boolean integer type argument}} +}; + +struct not_a_fam { + int count; + struct bar *non_fam __counted_by(count); // expected-error {{'counted_by' only applies to C99 flexible array members}} +}; + +struct not_a_c99_fam { + int count; + struct bar *non_c99_fam[0] __counted_by(count); // expected-error {{'counted_by' only applies to C99 flexible array members}} +}; + +struct annotated_with_anon_struct { + unsigned long flags; + struct { + unsigned char count; + int array[] __counted_by(crount); // expected-error {{use of undeclared identifier 'crount'}} + }; +}; -- GitLab From c587483da0b50efa04146fde205da1d16731e12e Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Sun, 19 May 2024 06:21:40 -0700 Subject: [PATCH 024/793] Revert "[Bounds-Safety] Fix `pragma-attribute-supported-attributes-list.test`" Issue #92687 This reverts commit 112eadd55f06bee15caadff688ea0b45acbfa804. --- clang/test/Misc/pragma-attribute-supported-attributes-list.test | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 99732694f72a..fd0e6d71baa8 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -63,6 +63,7 @@ // CHECK-NEXT: CoroOnlyDestroyWhenComplete (SubjectMatchRule_record) // CHECK-NEXT: CoroReturnType (SubjectMatchRule_record) // CHECK-NEXT: CoroWrapper (SubjectMatchRule_function) +// CHECK-NEXT: CountedBy (SubjectMatchRule_field) // CHECK-NEXT: DLLExport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface) // CHECK-NEXT: DLLImport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface) // CHECK-NEXT: Destructor (SubjectMatchRule_function) -- GitLab From 10edb4991c12738e60843d55cd9edbf6d702d9eb Mon Sep 17 00:00:00 2001 From: Alex Voicu Date: Sun, 19 May 2024 16:59:03 +0300 Subject: [PATCH 025/793] [Clang][CodeGen] Start migrating away from assuming the Default AS is 0 (#88182) At the moment, Clang is rather liberal in assuming that 0 (and by extension unqualified) is always a safe default. This does not work for targets that actually use a different value for the default / generic AS (for example, the SPIRV that obtains from HIPSPV or SYCL). This patch is a first, fairly safe step towards trying to clear things up by querying a modules' default AS from the target, rather than assuming it's 0, alongside fixing a few places where things break / we encode the 0 == DefaultAS assumption. A bunch of existing tests are extended to check for non-zero default AS usage. --- clang/lib/CodeGen/CGException.cpp | 5 +- clang/lib/CodeGen/CGExprCXX.cpp | 7 +- clang/lib/CodeGen/CodeGenModule.cpp | 3 +- clang/lib/CodeGen/CodeGenTypeCache.h | 2 +- .../CodeGenCXX/dynamic-cast-address-space.cpp | 123 ++++++++++++++++-- clang/test/CodeGenCXX/eh.cpp | 6 +- clang/test/CodeGenCXX/nrvo.cpp | 4 +- .../template-param-objects-address-space.cpp | 10 ++ ...w-expression-typeinfo-in-address-space.cpp | 2 + .../try-catch-with-address-space.cpp | 7 +- .../typeid-cxx11-with-address-space.cpp | 4 + .../CodeGenCXX/typeid-with-address-space.cpp | 11 ++ .../typeinfo-with-address-space.cpp | 7 + .../vtable-assume-load-address-space.cpp | 110 ++++++++++------ ...e-pointer-initialization-address-space.cpp | 7 + clang/test/CodeGenCXX/vtt-address-space.cpp | 7 + clang/test/CodeGenCXX/wasm-eh.cpp | 4 +- llvm/examples/ExceptionDemo/ExceptionDemo.cpp | 2 +- llvm/include/llvm/IR/Intrinsics.td | 4 +- .../WebAssembly/lower-em-exceptions.ll | 6 +- .../GVNHoist/infinite-loop-indirect.ll | 6 +- llvm/test/Transforms/Inline/inline_invoke.ll | 10 +- .../Transforms/LICM/scalar-promote-unwind.ll | 6 +- .../LowerTypeTests/cfi-unwind-direct-call.ll | 6 +- .../Transforms/NewGVN/2011-09-07-TypeIdFor.ll | 14 +- .../mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td | 2 +- mlir/test/Target/LLVMIR/Import/intrinsic.ll | 4 +- .../test/Target/LLVMIR/llvmir-intrinsics.mlir | 2 +- 28 files changed, 283 insertions(+), 98 deletions(-) diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 34f289334a7d..8acda3f2eb86 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -1052,7 +1052,8 @@ static void emitWasmCatchPadBlock(CodeGenFunction &CGF, CGF.Builder.CreateStore(Exn, CGF.getExceptionSlot()); llvm::CallInst *Selector = CGF.Builder.CreateCall(GetSelectorFn, CPI); - llvm::Function *TypeIDFn = CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); + llvm::Function *TypeIDFn = + CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for, {CGF.VoidPtrTy}); // If there's only a single catch-all, branch directly to its handler. if (CatchScope.getNumHandlers() == 1 && @@ -1137,7 +1138,7 @@ static void emitCatchDispatchBlock(CodeGenFunction &CGF, // Select the right handler. llvm::Function *llvm_eh_typeid_for = - CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); + CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for, {CGF.VoidPtrTy}); llvm::Type *argTy = llvm_eh_typeid_for->getArg(0)->getType(); LangAS globAS = CGF.CGM.GetGlobalVarAddressSpace(nullptr); diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index c18c36d3f3f3..0cfdb7effe47 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -2216,7 +2216,12 @@ static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E, } llvm::Value *CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) { - llvm::Type *PtrTy = llvm::PointerType::getUnqual(getLLVMContext()); + // Ideally, we would like to use GlobalsInt8PtrTy here, however, we cannot, + // primarily because the result of applying typeid is a value of type + // type_info, which is declared & defined by the standard library + // implementation and expects to operate on the generic (default) AS. + // https://reviews.llvm.org/D157452 has more context, and a possible solution. + llvm::Type *PtrTy = Int8PtrTy; LangAS GlobAS = CGM.GetGlobalVarAddressSpace(nullptr); auto MaybeASCast = [=](auto &&TypeInfo) { diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 489c08a4d481..227813ad44e8 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -368,7 +368,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, IntTy = llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getIntWidth()); IntPtrTy = llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getMaxPointerWidth()); - Int8PtrTy = llvm::PointerType::get(LLVMContext, 0); + Int8PtrTy = llvm::PointerType::get(LLVMContext, + C.getTargetAddressSpace(LangAS::Default)); const llvm::DataLayout &DL = M.getDataLayout(); AllocaInt8PtrTy = llvm::PointerType::get(LLVMContext, DL.getAllocaAddrSpace()); diff --git a/clang/lib/CodeGen/CodeGenTypeCache.h b/clang/lib/CodeGen/CodeGenTypeCache.h index 083d69214fb3..e273ebe3b060 100644 --- a/clang/lib/CodeGen/CodeGenTypeCache.h +++ b/clang/lib/CodeGen/CodeGenTypeCache.h @@ -51,7 +51,7 @@ struct CodeGenTypeCache { llvm::IntegerType *PtrDiffTy; }; - /// void*, void** in address space 0 + /// void*, void** in the target's default address space (often 0) union { llvm::PointerType *UnqualPtrTy; llvm::PointerType *VoidPtrTy; diff --git a/clang/test/CodeGenCXX/dynamic-cast-address-space.cpp b/clang/test/CodeGenCXX/dynamic-cast-address-space.cpp index 83a408984b76..3d5e32516c7a 100644 --- a/clang/test/CodeGenCXX/dynamic-cast-address-space.cpp +++ b/clang/test/CodeGenCXX/dynamic-cast-address-space.cpp @@ -1,24 +1,127 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --no-generate-body-for-unused-prefixes --version 4 // RUN: %clang_cc1 -I%S %s -triple amdgcn-amd-amdhsa -emit-llvm -fcxx-exceptions -fexceptions -o - | FileCheck %s +// RUN: %clang_cc1 -I%S %s -triple spirv64-unknown-unknown -fsycl-is-device -emit-llvm -fcxx-exceptions -fexceptions -o - | FileCheck %s --check-prefix=WITH-NONZERO-DEFAULT-AS + struct A { virtual void f(); }; struct B : A { }; -// CHECK: {{define.*@_Z1fP1A}} -// CHECK-SAME: personality ptr @__gxx_personality_v0 B fail; +//. +// CHECK: @_ZTV1B = linkonce_odr unnamed_addr addrspace(1) constant { [3 x ptr addrspace(1)] } { [3 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) @_ZTI1B, ptr addrspace(1) addrspacecast (ptr @_ZN1A1fEv to ptr addrspace(1))] }, comdat, align 8 +// CHECK: @fail = addrspace(1) global { ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, i32 0, i32 2) }, align 8 +// CHECK: @_ZTI1A = external addrspace(1) constant ptr addrspace(1) +// CHECK: @_ZTVN10__cxxabiv120__si_class_type_infoE = external addrspace(1) global [0 x ptr addrspace(1)] +// CHECK: @_ZTS1B = linkonce_odr addrspace(1) constant [3 x i8] c"1B\00", comdat, align 1 +// CHECK: @_ZTI1B = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1B, ptr addrspace(1) @_ZTI1A }, comdat, align 8 +// CHECK: @__oclc_ABI_version = weak_odr hidden local_unnamed_addr addrspace(4) constant i32 500 +//. +// WITH-NONZERO-DEFAULT-AS: @_ZTV1B = linkonce_odr unnamed_addr addrspace(1) constant { [3 x ptr addrspace(1)] } { [3 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) @_ZTI1B, ptr addrspace(1) addrspacecast (ptr @_ZN1A1fEv to ptr addrspace(1))] }, comdat, align 8 +// WITH-NONZERO-DEFAULT-AS: @fail = addrspace(1) global { ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, i32 0, i32 2) }, align 8 +// WITH-NONZERO-DEFAULT-AS: @_ZTI1A = external addrspace(1) constant ptr addrspace(1) +// WITH-NONZERO-DEFAULT-AS: @_ZTVN10__cxxabiv120__si_class_type_infoE = external addrspace(1) global [0 x ptr addrspace(1)] +// WITH-NONZERO-DEFAULT-AS: @_ZTS1B = linkonce_odr addrspace(1) constant [3 x i8] c"1B\00", comdat, align 1 +// WITH-NONZERO-DEFAULT-AS: @_ZTI1B = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1B, ptr addrspace(1) @_ZTI1A }, comdat, align 8 +//. +// CHECK-LABEL: define dso_local noundef nonnull align 8 dereferenceable(8) ptr @_Z1fP1A( +// CHECK-SAME: ptr noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] personality ptr @__gxx_personality_v0 { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[RETVAL:%.*]] = alloca ptr, align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) +// CHECK-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 8, addrspace(5) +// CHECK-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4, addrspace(5) +// CHECK-NEXT: [[RETVAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[RETVAL]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR_ASCAST]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = call ptr @__dynamic_cast(ptr [[TMP0]], ptr addrspace(1) @_ZTI1A, ptr addrspace(1) @_ZTI1B, i64 0) #[[ATTR3:[0-9]+]] +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP1]], null +// CHECK-NEXT: br i1 [[TMP2]], label [[DYNAMIC_CAST_BAD_CAST:%.*]], label [[DYNAMIC_CAST_END:%.*]] +// CHECK: dynamic_cast.bad_cast: +// CHECK-NEXT: invoke void @__cxa_bad_cast() #[[ATTR4:[0-9]+]] +// CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] +// CHECK: invoke.cont: +// CHECK-NEXT: unreachable +// CHECK: dynamic_cast.end: +// CHECK-NEXT: br label [[TRY_CONT:%.*]] +// CHECK: lpad: +// CHECK-NEXT: [[TMP3:%.*]] = landingpad { ptr, i32 } +// CHECK-NEXT: catch ptr null +// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { ptr, i32 } [[TMP3]], 0 +// CHECK-NEXT: store ptr [[TMP4]], ptr addrspace(5) [[EXN_SLOT]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP3]], 1 +// CHECK-NEXT: store i32 [[TMP5]], ptr addrspace(5) [[EHSELECTOR_SLOT]], align 4 +// CHECK-NEXT: br label [[CATCH:%.*]] +// CHECK: catch: +// CHECK-NEXT: [[EXN:%.*]] = load ptr, ptr addrspace(5) [[EXN_SLOT]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = call ptr @__cxa_begin_catch(ptr [[EXN]]) #[[ATTR3]] +// CHECK-NEXT: call void @__cxa_end_catch() +// CHECK-NEXT: br label [[TRY_CONT]] +// CHECK: try.cont: +// CHECK-NEXT: ret ptr addrspacecast (ptr addrspace(1) @fail to ptr) +// +// WITH-NONZERO-DEFAULT-AS-LABEL: define spir_func noundef align 8 dereferenceable(8) ptr addrspace(4) @_Z1fP1A( +// WITH-NONZERO-DEFAULT-AS-SAME: ptr addrspace(4) noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] personality ptr @__gxx_personality_v0 { +// WITH-NONZERO-DEFAULT-AS-NEXT: entry: +// WITH-NONZERO-DEFAULT-AS-NEXT: [[RETVAL:%.*]] = alloca ptr addrspace(4), align 8 +// WITH-NONZERO-DEFAULT-AS-NEXT: [[A_ADDR:%.*]] = alloca ptr addrspace(4), align 8 +// WITH-NONZERO-DEFAULT-AS-NEXT: [[EXN_SLOT:%.*]] = alloca ptr addrspace(4), align 8 +// WITH-NONZERO-DEFAULT-AS-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 +// WITH-NONZERO-DEFAULT-AS-NEXT: [[RETVAL_ASCAST:%.*]] = addrspacecast ptr [[RETVAL]] to ptr addrspace(4) +// WITH-NONZERO-DEFAULT-AS-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr [[A_ADDR]] to ptr addrspace(4) +// WITH-NONZERO-DEFAULT-AS-NEXT: store ptr addrspace(4) [[A]], ptr addrspace(4) [[A_ADDR_ASCAST]], align 8 +// WITH-NONZERO-DEFAULT-AS-NEXT: [[TMP0:%.*]] = load ptr addrspace(4), ptr addrspace(4) [[A_ADDR_ASCAST]], align 8 +// WITH-NONZERO-DEFAULT-AS-NEXT: [[TMP1:%.*]] = call spir_func ptr addrspace(4) @__dynamic_cast(ptr addrspace(4) [[TMP0]], ptr addrspace(1) @_ZTI1A, ptr addrspace(1) @_ZTI1B, i64 0) #[[ATTR3:[0-9]+]] +// WITH-NONZERO-DEFAULT-AS-NEXT: [[TMP2:%.*]] = icmp eq ptr addrspace(4) [[TMP1]], null +// WITH-NONZERO-DEFAULT-AS-NEXT: br i1 [[TMP2]], label [[DYNAMIC_CAST_BAD_CAST:%.*]], label [[DYNAMIC_CAST_END:%.*]] +// WITH-NONZERO-DEFAULT-AS: dynamic_cast.bad_cast: +// WITH-NONZERO-DEFAULT-AS-NEXT: invoke spir_func void @__cxa_bad_cast() #[[ATTR4:[0-9]+]] +// WITH-NONZERO-DEFAULT-AS-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] +// WITH-NONZERO-DEFAULT-AS: invoke.cont: +// WITH-NONZERO-DEFAULT-AS-NEXT: unreachable +// WITH-NONZERO-DEFAULT-AS: dynamic_cast.end: +// WITH-NONZERO-DEFAULT-AS-NEXT: br label [[TRY_CONT:%.*]] +// WITH-NONZERO-DEFAULT-AS: lpad: +// WITH-NONZERO-DEFAULT-AS-NEXT: [[TMP3:%.*]] = landingpad { ptr addrspace(4), i32 } +// WITH-NONZERO-DEFAULT-AS-NEXT: catch ptr addrspace(4) null +// WITH-NONZERO-DEFAULT-AS-NEXT: [[TMP4:%.*]] = extractvalue { ptr addrspace(4), i32 } [[TMP3]], 0 +// WITH-NONZERO-DEFAULT-AS-NEXT: store ptr addrspace(4) [[TMP4]], ptr [[EXN_SLOT]], align 8 +// WITH-NONZERO-DEFAULT-AS-NEXT: [[TMP5:%.*]] = extractvalue { ptr addrspace(4), i32 } [[TMP3]], 1 +// WITH-NONZERO-DEFAULT-AS-NEXT: store i32 [[TMP5]], ptr [[EHSELECTOR_SLOT]], align 4 +// WITH-NONZERO-DEFAULT-AS-NEXT: br label [[CATCH:%.*]] +// WITH-NONZERO-DEFAULT-AS: catch: +// WITH-NONZERO-DEFAULT-AS-NEXT: [[EXN:%.*]] = load ptr addrspace(4), ptr [[EXN_SLOT]], align 8 +// WITH-NONZERO-DEFAULT-AS-NEXT: [[TMP6:%.*]] = call spir_func ptr addrspace(4) @__cxa_begin_catch(ptr addrspace(4) [[EXN]]) #[[ATTR3]] +// WITH-NONZERO-DEFAULT-AS-NEXT: call spir_func void @__cxa_end_catch() +// WITH-NONZERO-DEFAULT-AS-NEXT: br label [[TRY_CONT]] +// WITH-NONZERO-DEFAULT-AS: try.cont: +// WITH-NONZERO-DEFAULT-AS-NEXT: ret ptr addrspace(4) addrspacecast (ptr addrspace(1) @fail to ptr addrspace(4)) +// const B& f(A *a) { try { - // CHECK: call ptr @__dynamic_cast - // CHECK: br i1 - // CHECK: invoke void @__cxa_bad_cast() [[NR:#[0-9]+]] dynamic_cast(*a); } catch (...) { - // CHECK: landingpad { ptr, i32 } - // CHECK-NEXT: catch ptr null } return fail; } -// CHECK: declare ptr @__dynamic_cast(ptr, ptr addrspace(1), ptr addrspace(1), i64) [[NUW_RO:#[0-9]+]] -// CHECK: attributes [[NUW_RO]] = { nounwind willreturn memory(read) } -// CHECK: attributes [[NR]] = { noreturn } +//. +// CHECK: attributes #[[ATTR0]] = { mustprogress noinline optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +// CHECK: attributes #[[ATTR1:[0-9]+]] = { nounwind willreturn memory(read) } +// CHECK: attributes #[[ATTR2:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +// CHECK: attributes #[[ATTR3]] = { nounwind } +// CHECK: attributes #[[ATTR4]] = { noreturn } +//. +// WITH-NONZERO-DEFAULT-AS: attributes #[[ATTR0]] = { convergent mustprogress noinline norecurse nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +// WITH-NONZERO-DEFAULT-AS: attributes #[[ATTR1:[0-9]+]] = { nounwind willreturn memory(read) } +// WITH-NONZERO-DEFAULT-AS: attributes #[[ATTR2:[0-9]+]] = { convergent nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +// WITH-NONZERO-DEFAULT-AS: attributes #[[ATTR3]] = { nounwind } +// WITH-NONZERO-DEFAULT-AS: attributes #[[ATTR4]] = { noreturn } +//. +// CHECK: [[META0:![0-9]+]] = !{i32 1, !"amdhsa_code_object_version", i32 500} +// CHECK: [[META1:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} +// CHECK: [[META2:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"} +//. +// WITH-NONZERO-DEFAULT-AS: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} +// WITH-NONZERO-DEFAULT-AS: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"} +//. diff --git a/clang/test/CodeGenCXX/eh.cpp b/clang/test/CodeGenCXX/eh.cpp index 5c592a96e27b..f174b5d84fdf 100644 --- a/clang/test/CodeGenCXX/eh.cpp +++ b/clang/test/CodeGenCXX/eh.cpp @@ -81,7 +81,7 @@ namespace test5 { // CHECK: invoke void @__cxa_throw(ptr [[EXNOBJ]], ptr @_ZTIN5test51AE, ptr @_ZN5test51AD1Ev) [[NR]] // CHECK-NEXT: to label {{%.*}} unwind label %[[HANDLER:[^ ]*]] // : [[HANDLER]]: (can't check this in Release-Asserts builds) -// CHECK: {{%.*}} = call i32 @llvm.eh.typeid.for(ptr @_ZTIN5test51AE) +// CHECK: {{%.*}} = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIN5test51AE) } namespace test6 { @@ -96,7 +96,7 @@ namespace test6 { // PR7127 namespace test7 { -// CHECK-LABEL: define{{.*}} i32 @_ZN5test73fooEv() +// CHECK-LABEL: define{{.*}} i32 @_ZN5test73fooEv() // CHECK-SAME: personality ptr @__gxx_personality_v0 int foo() { // CHECK: [[CAUGHTEXNVAR:%.*]] = alloca ptr @@ -119,7 +119,7 @@ namespace test7 { // CHECK-NEXT: store i32 [[SELECTOR]], ptr [[SELECTORVAR]] // CHECK-NEXT: br label // CHECK: [[SELECTOR:%.*]] = load i32, ptr [[SELECTORVAR]] -// CHECK-NEXT: [[T0:%.*]] = call i32 @llvm.eh.typeid.for(ptr @_ZTIi) +// CHECK-NEXT: [[T0:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) // CHECK-NEXT: icmp eq i32 [[SELECTOR]], [[T0]] // CHECK-NEXT: br i1 // CHECK: [[T0:%.*]] = load ptr, ptr [[CAUGHTEXNVAR]] diff --git a/clang/test/CodeGenCXX/nrvo.cpp b/clang/test/CodeGenCXX/nrvo.cpp index 33dc4cf9dbc8..23ac04511514 100644 --- a/clang/test/CodeGenCXX/nrvo.cpp +++ b/clang/test/CodeGenCXX/nrvo.cpp @@ -628,7 +628,7 @@ void may_throw(); // CHECK-EH-03-NEXT: br label [[CATCH_DISPATCH:%.*]] // CHECK-EH-03: catch.dispatch: // CHECK-EH-03-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 -// CHECK-EH-03-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for(ptr @_ZTI1X) #[[ATTR7]] +// CHECK-EH-03-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTI1X) #[[ATTR7]] // CHECK-EH-03-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[SEL]], [[TMP3]] // CHECK-EH-03-NEXT: br i1 [[MATCHES]], label [[CATCH:%.*]], label [[EH_RESUME:%.*]] // CHECK-EH-03: catch: @@ -707,7 +707,7 @@ void may_throw(); // CHECK-EH-11-NEXT: br label [[CATCH_DISPATCH:%.*]] // CHECK-EH-11: catch.dispatch: // CHECK-EH-11-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 -// CHECK-EH-11-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for(ptr @_ZTI1X) #[[ATTR6]] +// CHECK-EH-11-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTI1X) #[[ATTR6]] // CHECK-EH-11-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[SEL]], [[TMP3]] // CHECK-EH-11-NEXT: br i1 [[MATCHES]], label [[CATCH:%.*]], label [[EH_RESUME:%.*]] // CHECK-EH-11: catch: diff --git a/clang/test/CodeGenCXX/template-param-objects-address-space.cpp b/clang/test/CodeGenCXX/template-param-objects-address-space.cpp index b54dcfe77934..b3733decdb55 100644 --- a/clang/test/CodeGenCXX/template-param-objects-address-space.cpp +++ b/clang/test/CodeGenCXX/template-param-objects-address-space.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -std=c++20 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple spirv64-unknown-unknown -fsycl-is-device -std=c++20 %s -emit-llvm -o - | FileCheck %s --check-prefix=WITH-NONZERO-DEFAULT-AS struct S { char buf[32]; }; template constexpr const char *begin() { return s.buf; } @@ -8,25 +9,34 @@ extern const void *callee(const S*); template constexpr const void* observable_addr() { return callee(&s); } // CHECK: [[HELLO:@_ZTAXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEE]] +// WITH-NONZERO-DEFAULT-AS: [[HELLO:@_ZTAXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEE]] // CHECK-SAME: = linkonce_odr addrspace(1) constant { <{ [11 x i8], [21 x i8] }> } { <{ [11 x i8], [21 x i8] }> <{ [11 x i8] c"hello world", [21 x i8] zeroinitializer }> }, comdat // CHECK: @p // CHECK-SAME: addrspace(1) global ptr addrspacecast (ptr addrspace(1) [[HELLO]] to ptr) +// WITH-NONZERO-DEFAULT-AS: addrspace(1) global ptr addrspace(4) addrspacecast (ptr addrspace(1) [[HELLO]] to ptr addrspace(4)) const char *p = begin(); // CHECK: @q // CHECK-SAME: addrspace(1) global ptr addrspacecast (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) [[HELLO]], i64 11) to ptr) +// WITH-NONZERO-DEFAULT-AS: addrspace(1) global ptr addrspace(4) addrspacecast (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) [[HELLO]], i64 11) to ptr addrspace(4)) const char *q = end(); const void *(*r)() = &retval; // CHECK: @s // CHECK-SAME: addrspace(1) global ptr null +// WITH-NONZERO-DEFAULT-AS: addrspace(1) global ptr addrspace(4) null const void *s = observable_addr(); // CHECK: define linkonce_odr noundef ptr @_Z6retvalIXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEEEPKvv() +// WITH-NONZERO-DEFAULT-AS: define linkonce_odr {{.*}} noundef ptr addrspace(4) @_Z6retvalIXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEEEPKvv() // CHECK: ret ptr addrspacecast (ptr addrspace(1) [[HELLO]] to ptr) +// WITH-NONZERO-DEFAULT-AS: ret ptr addrspace(4) addrspacecast (ptr addrspace(1) [[HELLO]] to ptr addrspace(4)) // CHECK: define linkonce_odr noundef ptr @_Z15observable_addrIXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEEEPKvv() +// WITH-NONZERO-DEFAULT-AS: define linkonce_odr {{.*}} noundef ptr addrspace(4) @_Z15observable_addrIXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEEEPKvv() // CHECK: %call = call noundef ptr @_Z6calleePK1S(ptr noundef addrspacecast (ptr addrspace(1) [[HELLO]] to ptr)) +// WITH-NONZERO-DEFAULT-AS: %call = call {{.*}} noundef ptr addrspace(4) @_Z6calleePK1S(ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) [[HELLO]] to ptr addrspace(4))) // CHECK: declare noundef ptr @_Z6calleePK1S(ptr noundef) +// WITH-NONZERO-DEFAULT-AS: declare {{.*}} noundef ptr addrspace(4) @_Z6calleePK1S(ptr addrspace(4) noundef) diff --git a/clang/test/CodeGenCXX/throw-expression-typeinfo-in-address-space.cpp b/clang/test/CodeGenCXX/throw-expression-typeinfo-in-address-space.cpp index d8c23d427e67..3acbdd8fd97e 100644 --- a/clang/test/CodeGenCXX/throw-expression-typeinfo-in-address-space.cpp +++ b/clang/test/CodeGenCXX/throw-expression-typeinfo-in-address-space.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple amdgcn-amd-amdhsa -emit-llvm -fcxx-exceptions -fexceptions -std=c++11 -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple spirv64-unknown-unknown -fsycl-is-device -emit-llvm -fcxx-exceptions -fexceptions -std=c++11 -o - | FileCheck %s --check-prefix=WITH-NONZERO-DEFAULT-AS struct X { ~X(); @@ -15,3 +16,4 @@ void f() { } // CHECK: declare void @__cxa_throw(ptr, ptr addrspace(1), ptr) +// WITH-NONZERO-DEFAULT-AS: declare{{.*}} void @__cxa_throw(ptr addrspace(4), ptr addrspace(1), ptr addrspace(4)) diff --git a/clang/test/CodeGenCXX/try-catch-with-address-space.cpp b/clang/test/CodeGenCXX/try-catch-with-address-space.cpp index 279d29f50fd4..412ac6c28725 100644 --- a/clang/test/CodeGenCXX/try-catch-with-address-space.cpp +++ b/clang/test/CodeGenCXX/try-catch-with-address-space.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -emit-llvm -o - -fcxx-exceptions -fexceptions | FileCheck %s +// RUN: %clang_cc1 %s -triple=spirv64-unknown-unknown -fsycl-is-device -emit-llvm -o - -fcxx-exceptions -fexceptions | FileCheck %s --check-prefix=WITH-NONZERO-DEFAULT-AS struct X { }; @@ -10,7 +11,8 @@ void f() { // CHECK: ptr addrspace(1) @_ZTI1X } catch (const X x) { // CHECK: catch ptr addrspace(1) @_ZTI1X - // CHECK: call i32 @llvm.eh.typeid.for(ptr addrspacecast (ptr addrspace(1) @_ZTI1X to ptr)) + // CHECK: call i32 @llvm.eh.typeid.for.p0(ptr addrspacecast (ptr addrspace(1) @_ZTI1X to ptr)) + // WITH-NONZERO-DEFAULT-AS: call i32 @llvm.eh.typeid.for.p4(ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTI1X to ptr addrspace(4))) } } @@ -20,6 +22,7 @@ void h() { // CHECK: ptr addrspace(1) @_ZTIPKc } catch (char const(&)[4]) { // CHECK: catch ptr addrspace(1) @_ZTIA4_c - // CHECK: call i32 @llvm.eh.typeid.for(ptr addrspacecast (ptr addrspace(1) @_ZTIA4_c to ptr)) + // CHECK: call i32 @llvm.eh.typeid.for.p0(ptr addrspacecast (ptr addrspace(1) @_ZTIA4_c to ptr)) + // WITH-NONZERO-DEFAULT-AS: call i32 @llvm.eh.typeid.for.p4(ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIA4_c to ptr addrspace(4))) } } diff --git a/clang/test/CodeGenCXX/typeid-cxx11-with-address-space.cpp b/clang/test/CodeGenCXX/typeid-cxx11-with-address-space.cpp index c4e7d36acff1..f6dc38ec9f29 100644 --- a/clang/test/CodeGenCXX/typeid-cxx11-with-address-space.cpp +++ b/clang/test/CodeGenCXX/typeid-cxx11-with-address-space.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -I%S %s -triple amdgcn-amd-amdhsa -emit-llvm -std=c++11 -o - | FileCheck %s +// RUN: %clang_cc1 -I%S %s -triple spirv64-unknown-unknown -fsycl-is-device -emit-llvm -std=c++11 -o - | FileCheck %s --check-prefix=WITH-NONZERO-DEFAULT-AS #include namespace Test1 { @@ -19,14 +20,17 @@ struct B : virtual A {}; struct C { int n; }; // CHECK: @_ZN5Test15itemsE ={{.*}} constant [4 x {{.*}}] [{{.*}} ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11AE to ptr), {{.*}} @_ZN5Test19make_implINS_1AEEEPvv {{.*}} ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11BE to ptr), {{.*}} @_ZN5Test19make_implINS_1BEEEPvv {{.*}} ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11CE to ptr), {{.*}} @_ZN5Test19make_implINS_1CEEEPvv {{.*}} ptr addrspacecast (ptr addrspace(1) @_ZTIi to ptr), {{.*}} @_ZN5Test19make_implIiEEPvv }] +// WITH-NONZERO-DEFAULT-AS: @_ZN5Test15itemsE ={{.*}} addrspace(1) constant [4 x {{.*}}] [{{.*}} ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIN5Test11AE to ptr addrspace(4)), {{.*}} @_ZN5Test19make_implINS_1AEEEPvv {{.*}} ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIN5Test11BE to ptr addrspace(4)), {{.*}} @_ZN5Test19make_implINS_1BEEEPvv {{.*}} ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIN5Test11CE to ptr addrspace(4)), {{.*}} @_ZN5Test19make_implINS_1CEEEPvv {{.*}} ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIi to ptr addrspace(4)), {{.*}} @_ZN5Test19make_implIiEEPvv }] extern constexpr Item items[] = { item("A"), item("B"), item("C"), item("int") }; // CHECK: @_ZN5Test11xE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11AE to ptr), align 8 +// WITH-NONZERO-DEFAULT-AS: @_ZN5Test11xE ={{.*}} addrspace(1) constant ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIN5Test11AE to ptr addrspace(4)), align 8 constexpr auto &x = items[0].ti; // CHECK: @_ZN5Test11yE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11BE to ptr), align 8 +// WITH-NONZERO-DEFAULT-AS: @_ZN5Test11yE ={{.*}} addrspace(1) constant ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIN5Test11BE to ptr addrspace(4)), align 8 constexpr auto &y = typeid(B{}); } diff --git a/clang/test/CodeGenCXX/typeid-with-address-space.cpp b/clang/test/CodeGenCXX/typeid-with-address-space.cpp index b439770a8b63..98af17f4fc88 100644 --- a/clang/test/CodeGenCXX/typeid-with-address-space.cpp +++ b/clang/test/CodeGenCXX/typeid-with-address-space.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -I%S %s -triple amdgcn-amd-amdhsa -emit-llvm -fcxx-exceptions -fexceptions -o - | FileCheck %s +// RUN: %clang_cc1 -I%S %s -triple spirv64-unknown-unknown -fsycl-is-device -emit-llvm -fcxx-exceptions -fexceptions -o - | FileCheck %s --check-prefix=WITH-NONZERO-DEFAULT-AS #include namespace Test1 { @@ -7,19 +8,23 @@ namespace Test1 { struct A { virtual void f(); }; // CHECK: @_ZN5Test16int_tiE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIi to ptr), align 8 +// WITH-NONZERO-DEFAULT-AS: @_ZN5Test16int_tiE ={{.*}} constant ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIi to ptr addrspace(4)), align 8 const std::type_info &int_ti = typeid(int); // CHECK: @_ZN5Test14A_tiE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11AE to ptr), align 8 +// WITH-NONZERO-DEFAULT-AS: @_ZN5Test14A_tiE ={{.*}} constant ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIN5Test11AE to ptr addrspace(4)), align 8 const std::type_info &A_ti = typeid(const volatile A &); volatile char c; // CHECK: @_ZN5Test14c_tiE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIc to ptr), align 8 +// WITH-NONZERO-DEFAULT-AS: @_ZN5Test14c_tiE ={{.*}} constant ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIc to ptr addrspace(4)), align 8 const std::type_info &c_ti = typeid(c); extern const double &d; // CHECK: @_ZN5Test14d_tiE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTId to ptr), align 8 +// WITH-NONZERO-DEFAULT-AS: @_ZN5Test14d_tiE ={{.*}} constant ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTId to ptr addrspace(4)), align 8 const std::type_info &d_ti = typeid(d); extern A &a; @@ -28,18 +33,24 @@ extern A &a; const std::type_info &a_ti = typeid(a); // CHECK: @_ZN5Test18A10_c_tiE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIA10_c to ptr), align 8 +// WITH-NONZERO-DEFAULT-AS: @_ZN5Test18A10_c_tiE ={{.*}} constant ptr addrspace(4) addrspacecast (ptr addrspace(1) @_ZTIA10_c to ptr addrspace(4)), align 8 const std::type_info &A10_c_ti = typeid(char const[10]); // CHECK-LABEL: define{{.*}} ptr @_ZN5Test11fEv // CHECK-SAME: personality ptr @__gxx_personality_v0 +// WITH-NONZERO-DEFAULT-AS-LABEL: define{{.*}} ptr addrspace(4) @_ZN5Test11fEv +// WITH-NONZERO-DEFAULT-AS-SAME: personality ptr @__gxx_personality_v0 const char *f() { try { // CHECK: br i1 // CHECK: invoke void @__cxa_bad_typeid() [[NR:#[0-9]+]] + // WITH-NONZERO-DEFAULT-AS: invoke{{.*}} void @__cxa_bad_typeid() [[NR:#[0-9]+]] return typeid(*static_cast(0)).name(); } catch (...) { // CHECK: landingpad { ptr, i32 } // CHECK-NEXT: catch ptr null + // WITH-NONZERO-DEFAULT-AS: landingpad { ptr addrspace(4), i32 } + // WITH-NONZERO-DEFAULT-AS-NEXT: catch ptr addrspace(4) null } return 0; diff --git a/clang/test/CodeGenCXX/typeinfo-with-address-space.cpp b/clang/test/CodeGenCXX/typeinfo-with-address-space.cpp index 80f6ab0903e5..350303cc6e9b 100644 --- a/clang/test/CodeGenCXX/typeinfo-with-address-space.cpp +++ b/clang/test/CodeGenCXX/typeinfo-with-address-space.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -I%S %s -triple amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck %s -check-prefix=AS +// RUN: %clang_cc1 -I%S %s -triple spirv64-unknown-unknown -fsycl-is-device -emit-llvm -o - | FileCheck %s -check-prefix=NONZERO-DEFAULT-AS // RUN: %clang_cc1 -I%S %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s -check-prefix=NO-AS #include @@ -25,24 +26,30 @@ class B : A { unsigned long Fn(B& b) { // AS: %call = call noundef zeroext i1 @_ZNKSt9type_infoeqERKS_(ptr {{.*}} addrspacecast (ptr addrspace(1) @_ZTISt9type_info to ptr), ptr {{.*}} %2) +// NONZERO-DEFAULT-AS: %call = call{{.*}} noundef zeroext i1 @_ZNKSt9type_infoeqERKS_(ptr addrspace(4) {{.*}} addrspacecast (ptr addrspace(1) @_ZTISt9type_info to ptr addrspace(4)), ptr addrspace(4) {{.*}} %2) // NO-AS: %call = call noundef zeroext i1 @_ZNKSt9type_infoeqERKS_(ptr {{.*}} @_ZTISt9type_info, ptr {{.*}} %2) if (typeid(std::type_info) == typeid(b)) return 42; // AS: %call2 = call noundef zeroext i1 @_ZNKSt9type_infoneERKS_(ptr {{.*}} addrspacecast (ptr addrspace(1) @_ZTIi to ptr), ptr {{.*}} %5) +// NONZERO-DEFAULT-AS: %call2 = call{{.*}} noundef zeroext i1 @_ZNKSt9type_infoneERKS_(ptr addrspace(4) {{.*}} addrspacecast (ptr addrspace(1) @_ZTIi to ptr addrspace(4)), ptr addrspace(4) {{.*}} %5) // NO-AS: %call2 = call noundef zeroext i1 @_ZNKSt9type_infoneERKS_(ptr {{.*}} @_ZTIi, ptr {{.*}} %5) if (typeid(int) != typeid(b)) return 1712; // AS: %call5 = call noundef ptr @_ZNKSt9type_info4nameEv(ptr {{.*}} addrspacecast (ptr addrspace(1) @_ZTI1A to ptr)) +// NONZERO-DEFAULT-AS: %call5 = call{{.*}} noundef ptr addrspace(4) @_ZNKSt9type_info4nameEv(ptr addrspace(4) {{.*}} addrspacecast (ptr addrspace(1) @_ZTI1A to ptr addrspace(4))) // NO-AS: %call5 = call noundef ptr @_ZNKSt9type_info4nameEv(ptr {{.*}} @_ZTI1A) // AS: %call7 = call noundef ptr @_ZNKSt9type_info4nameEv(ptr {{.*}} %8) +// NONZERO-DEFAULT-AS: %call7 = call{{.*}} noundef ptr addrspace(4) @_ZNKSt9type_info4nameEv(ptr addrspace(4) {{.*}} %8) // NO-AS: %call7 = call noundef ptr @_ZNKSt9type_info4nameEv(ptr {{.*}} %8) if (typeid(A).name() == typeid(b).name()) return 0; // AS: %call11 = call noundef zeroext i1 @_ZNKSt9type_info6beforeERKS_(ptr {{.*}} %11, ptr {{.*}} addrspacecast (ptr addrspace(1) @_ZTIf to ptr)) +// NONZERO-DEFAULT-AS: %call11 = call{{.*}} noundef zeroext i1 @_ZNKSt9type_info6beforeERKS_(ptr addrspace(4) {{.*}} %11, ptr addrspace(4) {{.*}} addrspacecast (ptr addrspace(1) @_ZTIf to ptr addrspace(4))) // NO-AS: %call11 = call noundef zeroext i1 @_ZNKSt9type_info6beforeERKS_(ptr {{.*}} %11, ptr {{.*}} @_ZTIf) if (typeid(b).before(typeid(float))) return 1; // AS: %call15 = call noundef i64 @_ZNKSt9type_info9hash_codeEv(ptr {{.*}} %14) +// NONZERO-DEFAULT-AS: %call15 = call{{.*}} noundef i64 @_ZNKSt9type_info9hash_codeEv(ptr addrspace(4) {{.*}} %14) // NO-AS: %call15 = call noundef i64 @_ZNKSt9type_info9hash_codeEv(ptr {{.*}} %14) return typeid(b).hash_code(); } diff --git a/clang/test/CodeGenCXX/vtable-assume-load-address-space.cpp b/clang/test/CodeGenCXX/vtable-assume-load-address-space.cpp index d765fe94d9b0..ecafa99d8be0 100644 --- a/clang/test/CodeGenCXX/vtable-assume-load-address-space.cpp +++ b/clang/test/CodeGenCXX/vtable-assume-load-address-space.cpp @@ -1,14 +1,17 @@ // RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -std=c++11 -emit-llvm -o %t.ll -O1 -disable-llvm-passes -fms-extensions -fstrict-vtable-pointers +// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-passes -fms-extensions -fstrict-vtable-pointers +// RUN: %clang_cc1 %s -triple=spirv64-unknown-unknown -fsycl-is-device -std=c++11 -emit-llvm -o %t.ll -O1 -disable-llvm-passes -fms-extensions -fstrict-vtable-pointers // FIXME: Assume load should not require -fstrict-vtable-pointers // RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s // RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s // RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s // RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s -// RUN: FileCheck --check-prefix=CHECK5 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s // RUN: FileCheck --check-prefix=CHECK6 --input-file=%t.ll %s // RUN: FileCheck --check-prefix=CHECK7 --input-file=%t.ll %s // RUN: FileCheck --check-prefix=CHECK8 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK9 --input-file=%t.ll %s namespace test1 { struct A { @@ -23,8 +26,8 @@ struct B : A { void g(A *a) { a->foo(); } // CHECK1-LABEL: define{{.*}} void @_ZN5test14fooAEv() -// CHECK1: call void @_ZN5test11AC1Ev(ptr -// CHECK1: %[[VTABLE:.*]] = load ptr addrspace(1), ptr %{{.*}} +// CHECK1: call{{.*}} void @_ZN5test11AC1Ev(ptr {{((addrspace(4)){0,1})}} +// CHECK1: %[[VTABLE:.*]] = load ptr addrspace(1), ptr {{((addrspace(4)){0,1})}}{{.*}}%{{.*}} // CHECK1: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test11AE, i32 0, i32 0, i32 2) // CHECK1: call void @llvm.assume(i1 %[[CMP]]) // CHECK1-LABEL: {{^}}} @@ -35,8 +38,8 @@ void fooA() { } // CHECK1-LABEL: define{{.*}} void @_ZN5test14fooBEv() -// CHECK1: call void @_ZN5test11BC1Ev(ptr {{[^,]*}} %{{.*}}) -// CHECK1: %[[VTABLE:.*]] = load ptr addrspace(1), ptr %{{.*}} +// CHECK1: call{{.*}} void @_ZN5test11BC1Ev(ptr {{[^,]*}} %{{.*}}) +// CHECK1: %[[VTABLE:.*]] = load ptr addrspace(1), ptr {{((addrspace(4)){0,1})}}{{.*}}%{{.*}} // CHECK1: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test11BE, i32 0, i32 0, i32 2) // CHECK1: call void @llvm.assume(i1 %[[CMP]]) // CHECK1-LABEL: {{^}}} @@ -46,7 +49,7 @@ void fooB() { g(&b); } // there should not be any assumes in the ctor that calls base ctor -// CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(ptr +// CHECK1-LABEL: define linkonce_odr{{.*}} void @_ZN5test11BC2Ev(ptr // CHECK1-NOT: @llvm.assume( // CHECK1-LABEL: {{^}}} } @@ -69,17 +72,17 @@ void g(A *a) { a->foo(); } void h(B *b) { b->bar(); } // CHECK2-LABEL: define{{.*}} void @_ZN5test24testEv() -// CHECK2: call void @_ZN5test21CC1Ev(ptr +// CHECK2: call{{.*}} void @_ZN5test21CC1Ev(ptr // CHECK2: %[[VTABLE:.*]] = load ptr addrspace(1), ptr {{.*}} // CHECK2: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test21CE, i32 0, i32 0, i32 2) // CHECK2: call void @llvm.assume(i1 %[[CMP]]) -// CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i64 8 -// CHECK2: %[[VTABLE2:.*]] = load ptr addrspace(1), ptr %[[ADD_PTR]] +// CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr {{((addrspace(4)){0,1})}}{{.*}}%{{.*}}, i64 8 +// CHECK2: %[[VTABLE2:.*]] = load ptr addrspace(1), ptr {{((addrspace(4)){0,1})}}{{.*}}%[[ADD_PTR]] // CHECK2: %[[CMP2:.*]] = icmp eq ptr addrspace(1) %[[VTABLE2]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test21CE, i32 0, i32 1, i32 2) // CHECK2: call void @llvm.assume(i1 %[[CMP2]]) -// CHECK2: call void @_ZN5test21gEPNS_1AE( +// CHECK2: call{{.*}} void @_ZN5test21gEPNS_1AE( // CHECK2-LABEL: {{^}}} void test() { @@ -106,7 +109,7 @@ struct C : virtual A, B { void g(B *a) { a->foo(); } // CHECK3-LABEL: define{{.*}} void @_ZN5test34testEv() -// CHECK3: call void @_ZN5test31CC1Ev(ptr +// CHECK3: call{{.*}} void @_ZN5test31CC1Ev(ptr // CHECK3: %[[CMP:.*]] = icmp eq ptr addrspace(1) %{{.*}}, getelementptr inbounds inrange(-24, 8) ({ [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test31CE, i32 0, i32 0, i32 3) // CHECK3: call void @llvm.assume(i1 %[[CMP]]) // CHECK3-LABLEL: } @@ -134,12 +137,12 @@ struct C : B { void g(C *c) { c->foo(); } // CHECK4-LABEL: define{{.*}} void @_ZN5test44testEv() -// CHECK4: call void @_ZN5test41CC1Ev(ptr -// CHECK4: %[[VTABLE:.*]] = load ptr addrspace(1), ptr %{{.*}} +// CHECK4: call{{.*}} void @_ZN5test41CC1Ev(ptr +// CHECK4: %[[VTABLE:.*]] = load ptr addrspace(1), ptr {{((addrspace(4)){0,1})}}{{.*}}%{{.*}} // CHECK4: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-32, 8) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test41CE, i32 0, i32 0, i32 4) // CHECK4: call void @llvm.assume(i1 %[[CMP]] -// CHECK4: %[[VTABLE2:.*]] = load ptr addrspace(1), ptr %{{.*}} +// CHECK4: %[[VTABLE2:.*]] = load ptr addrspace(1), ptr {{((addrspace(4)){0,1})}}{{.*}}%{{.*}} // CHECK4: %[[CMP2:.*]] = icmp eq ptr addrspace(1) %[[VTABLE2]], getelementptr inbounds inrange(-32, 8) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test41CE, i32 0, i32 0, i32 4) // CHECK4: call void @llvm.assume(i1 %[[CMP2]]) // CHECK4-LABEL: {{^}}} @@ -150,6 +153,27 @@ void test() { } } // test4 +namespace testMS { + +struct __declspec(novtable) S { + virtual void foo(); +}; + +void g(S &s) { s.foo(); } + +// if struct has novtable specifier, then we can't generate assumes +// CHECK-MS-LABEL: define dso_local void @"?test@testMS@@YAXXZ"() +// CHECK-MS: call x86_thiscallcc noundef ptr @"??0S@testMS@@QAE@XZ"( +// CHECK-MS-NOT: @llvm.assume +// CHECK-MS-LABEL: {{^}}} + +void test() { + S s; + g(s); +} + +} // testMS + namespace test6 { struct A { A(); @@ -161,17 +185,17 @@ struct B : A { }; // FIXME: Because A's vtable is external, and no virtual functions are hidden, // it's safe to generate assumption loads. -// CHECK5-LABEL: define{{.*}} void @_ZN5test61gEv() -// CHECK5: call void @_ZN5test61AC1Ev( -// CHECK5-NOT: call void @llvm.assume( +// CHECK6-LABEL: define{{.*}} void @_ZN5test61gEv() +// CHECK6: call{{.*}} void @_ZN5test61AC1Ev( +// CHECK6-NOT: call void @llvm.assume( // We can't emit assumption loads for B, because if we would refer to vtable // it would refer to functions that will not be able to find (like implicit // inline destructor). -// CHECK5-LABEL: call void @_ZN5test61BC1Ev( -// CHECK5-NOT: call void @llvm.assume( -// CHECK5-LABEL: {{^}}} +// CHECK6-LABEL: call{{.*}} void @_ZN5test61BC1Ev( +// CHECK6-NOT: call void @llvm.assume( +// CHECK6-LABEL: {{^}}} void g() { A *a = new A; B *b = new B; @@ -180,7 +204,7 @@ void g() { namespace test7 { // Because A's key function is defined here, vtable is generated in this TU -// CHECK6: @_ZTVN5test71AE ={{.*}} unnamed_addr addrspace(1) constant +// CHECK7: @_ZTVN5test71AE ={{.*}} unnamed_addr addrspace(1) constant struct A { A(); virtual void foo(); @@ -188,10 +212,10 @@ struct A { }; void A::foo() {} -// CHECK6-LABEL: define{{.*}} void @_ZN5test71gEv() -// CHECK6: call void @_ZN5test71AC1Ev( -// CHECK6: call void @llvm.assume( -// CHECK6-LABEL: {{^}}} +// CHECK7-LABEL: define{{.*}} void @_ZN5test71gEv() +// CHECK7: call{{.*}} void @_ZN5test71AC1Ev( +// CHECK7: call void @llvm.assume( +// CHECK7-LABEL: {{^}}} void g() { A *a = new A(); a->bar(); @@ -205,14 +229,14 @@ struct A { virtual void bar(); }; -// CHECK7-DAG: @_ZTVN5test81BE = available_externally unnamed_addr addrspace(1) constant +// CHECK8-DAG: @_ZTVN5test81BE = available_externally unnamed_addr addrspace(1) constant struct B : A { B(); void foo(); void bar(); }; -// CHECK7-DAG: @_ZTVN5test81CE = linkonce_odr unnamed_addr addrspace(1) constant +// CHECK8-DAG: @_ZTVN5test81CE = linkonce_odr unnamed_addr addrspace(1) constant struct C : A { C(); void bar(); @@ -227,14 +251,14 @@ struct D : A { }; void D::bar() {} -// CHECK7-DAG: @_ZTVN5test81EE = linkonce_odr unnamed_addr addrspace(1) constant +// CHECK8-DAG: @_ZTVN5test81EE = linkonce_odr unnamed_addr addrspace(1) constant struct E : A { E(); }; -// CHECK7-LABEL: define{{.*}} void @_ZN5test81bEv() -// CHECK7: call void @llvm.assume( -// CHECK7-LABEL: {{^}}} +// CHECK8-LABEL: define{{.*}} void @_ZN5test81bEv() +// CHECK8: call void @llvm.assume( +// CHECK8-LABEL: {{^}}} void b() { B b; b.bar(); @@ -243,26 +267,26 @@ void b() { // FIXME: C has inline virtual functions which prohibits as from generating // assumption loads, but because vtable is generated in this TU (key function // defined here) it would be correct to refer to it. -// CHECK7-LABEL: define{{.*}} void @_ZN5test81cEv() -// CHECK7-NOT: call void @llvm.assume( -// CHECK7-LABEL: {{^}}} +// CHECK8-LABEL: define{{.*}} void @_ZN5test81cEv() +// CHECK8-NOT: call void @llvm.assume( +// CHECK8-LABEL: {{^}}} void c() { C c; c.bar(); } // FIXME: We could generate assumption loads here. -// CHECK7-LABEL: define{{.*}} void @_ZN5test81dEv() -// CHECK7-NOT: call void @llvm.assume( -// CHECK7-LABEL: {{^}}} +// CHECK8-LABEL: define{{.*}} void @_ZN5test81dEv() +// CHECK8-NOT: call void @llvm.assume( +// CHECK8-LABEL: {{^}}} void d() { D d; d.bar(); } -// CHECK7-LABEL: define{{.*}} void @_ZN5test81eEv() -// CHECK7: call void @llvm.assume( -// CHECK7-LABEL: {{^}}} +// CHECK8-LABEL: define{{.*}} void @_ZN5test81eEv() +// CHECK8: call void @llvm.assume( +// CHECK8-LABEL: {{^}}} void e() { E e; e.bar(); @@ -276,9 +300,9 @@ struct S { __attribute__((visibility("hidden"))) virtual void doStuff(); }; -// CHECK8-LABEL: define{{.*}} void @_ZN5test94testEv() -// CHECK8-NOT: @llvm.assume( -// CHECK8: } +// CHECK9-LABEL: define{{.*}} void @_ZN5test94testEv() +// CHECK9-NOT: @llvm.assume( +// CHECK9: } void test() { S *s = new S(); s->doStuff(); diff --git a/clang/test/CodeGenCXX/vtable-pointer-initialization-address-space.cpp b/clang/test/CodeGenCXX/vtable-pointer-initialization-address-space.cpp index a3f12f0ebfc8..876d0845cc51 100644 --- a/clang/test/CodeGenCXX/vtable-pointer-initialization-address-space.cpp +++ b/clang/test/CodeGenCXX/vtable-pointer-initialization-address-space.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -std=c++11 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=spirv64-unknown-unknown -fsycl-is-device -std=c++11 -emit-llvm -o - | FileCheck %s --check-prefix=WITH-NONZERO-DEFAULT-AS struct Field { Field(); @@ -24,6 +25,7 @@ struct A : Base { // CHECK: store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1A, i32 0, i32 0, i32 2) // CHECK: call void @_ZN5FieldC1Ev( // CHECK: ret void +// WITH-NONZERO-DEFAULT-AS-LABEL: define{{.*}} void @_ZN1AC2Ev(ptr addrspace(4) {{[^,]*}} %this) unnamed_addr A::A() { } // CHECK-LABEL: define{{.*}} void @_ZN1AD2Ev(ptr {{[^,]*}} %this) unnamed_addr @@ -31,6 +33,7 @@ A::A() { } // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void +// WITH-NONZERO-DEFAULT-AS-LABEL: define{{.*}} void @_ZN1AD2Ev(ptr addrspace(4) {{[^,]*}} %this) unnamed_addr A::~A() { } struct B : Base { @@ -43,18 +46,22 @@ void f() { B b; } // CHECK-LABEL: define linkonce_odr void @_ZN1BC1Ev(ptr {{[^,]*}} %this) unnamed_addr // CHECK: call void @_ZN1BC2Ev( +// WITH-NONZERO-DEFAULT-AS-LABEL: define linkonce_odr{{.*}} void @_ZN1BC1Ev(ptr addrspace(4) {{[^,]*}} %this) unnamed_addr // CHECK-LABEL: define linkonce_odr void @_ZN1BD1Ev(ptr {{[^,]*}} %this) unnamed_addr // CHECK: call void @_ZN1BD2Ev( +// WITH-NONZERO-DEFAULT-AS-LABEL: define linkonce_odr{{.*}} void @_ZN1BD1Ev(ptr addrspace(4) {{[^,]*}} %this) unnamed_addr // CHECK-LABEL: define linkonce_odr void @_ZN1BC2Ev(ptr {{[^,]*}} %this) unnamed_addr // CHECK: call void @_ZN4BaseC2Ev( // CHECK: store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, i32 0, i32 2) // CHECK: call void @_ZN5FieldC1Ev // CHECK: ret void +// WITH-NONZERO-DEFAULT-AS-LABEL: define linkonce_odr{{.*}} void @_ZN1BC2Ev(ptr addrspace(4) {{[^,]*}} %this) unnamed_addr // CHECK-LABEL: define linkonce_odr void @_ZN1BD2Ev(ptr {{[^,]*}} %this) unnamed_addr // CHECK: store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, i32 0, i32 2) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void +// WITH-NONZERO-DEFAULT-AS-LABEL: define linkonce_odr{{.*}} void @_ZN1BD2Ev(ptr addrspace(4) {{[^,]*}} %this) unnamed_addr diff --git a/clang/test/CodeGenCXX/vtt-address-space.cpp b/clang/test/CodeGenCXX/vtt-address-space.cpp index 24f4e2a755da..4c3d0a534611 100644 --- a/clang/test/CodeGenCXX/vtt-address-space.cpp +++ b/clang/test/CodeGenCXX/vtt-address-space.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -std=c++11 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple=spirv64-unknown-unknown -fsycl-is-device -std=c++11 -emit-llvm -o - | FileCheck %s --check-prefix=WITH-NONZERO-DEFAULT-AS // This is the sample from the C++ Itanium ABI, p2.6.2. namespace Test { @@ -25,3 +26,9 @@ namespace Test { // CHECK: define linkonce_odr void @_ZN4Test2V2C2Ev(ptr noundef nonnull align 8 dereferenceable(20) %this, ptr addrspace(1) noundef %vtt) // CHECK: define linkonce_odr void @_ZN4Test2C1C2Ev(ptr noundef nonnull align 8 dereferenceable(12) %this, ptr addrspace(1) noundef %vtt) // CHECK: define linkonce_odr void @_ZN4Test2C2C2Ev(ptr noundef nonnull align 8 dereferenceable(12) %this, ptr addrspace(1) noundef %vtt) +// WITH-NONZERO-DEFAULT-AS: call {{.*}} void @_ZN4Test2V2C2Ev(ptr addrspace(4) noundef align 8 dereferenceable_or_null(20) %2, ptr addrspace(1) noundef getelementptr inbounds ([13 x ptr addrspace(1)], ptr addrspace(1) @_ZTTN4Test1DE, i64 0, i64 11)) +// WITH-NONZERO-DEFAULT-AS: call {{.*}} void @_ZN4Test2C1C2Ev(ptr addrspace(4) noundef align 8 dereferenceable_or_null(12) %this1, ptr addrspace(1) noundef getelementptr inbounds ([13 x ptr addrspace(1)], ptr addrspace(1) @_ZTTN4Test1DE, i64 0, i64 1)) +// WITH-NONZERO-DEFAULT-AS: call {{.*}} void @_ZN4Test2C2C2Ev(ptr addrspace(4) noundef align 8 dereferenceable_or_null(12) %3, ptr addrspace(1) noundef getelementptr inbounds ([13 x ptr addrspace(1)], ptr addrspace(1) @_ZTTN4Test1DE, i64 0, i64 3)) +// WITH-NONZERO-DEFAULT-AS: define linkonce_odr {{.*}} void @_ZN4Test2V2C2Ev(ptr addrspace(4) noundef align 8 dereferenceable_or_null(20) %this, ptr addrspace(1) noundef %vtt) +// WITH-NONZERO-DEFAULT-AS: define linkonce_odr {{.*}} void @_ZN4Test2C1C2Ev(ptr addrspace(4) noundef align 8 dereferenceable_or_null(12) %this, ptr addrspace(1) noundef %vtt) +// WITH-NONZERO-DEFAULT-AS: define linkonce_odr {{.*}} void @_ZN4Test2C2C2Ev(ptr addrspace(4) noundef align 8 dereferenceable_or_null(12) %this, ptr addrspace(1) noundef %vtt) diff --git a/clang/test/CodeGenCXX/wasm-eh.cpp b/clang/test/CodeGenCXX/wasm-eh.cpp index af023f52191b..1b17498ba9ce 100644 --- a/clang/test/CodeGenCXX/wasm-eh.cpp +++ b/clang/test/CodeGenCXX/wasm-eh.cpp @@ -34,7 +34,7 @@ void test0() { // CHECK-NEXT: %[[EXN:.*]] = call ptr @llvm.wasm.get.exception(token %[[CATCHPAD]]) // CHECK-NEXT: store ptr %[[EXN]], ptr %exn.slot // CHECK-NEXT: %[[SELECTOR:.*]] = call i32 @llvm.wasm.get.ehselector(token %[[CATCHPAD]]) -// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(ptr @_ZTIi) #7 +// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) #7 // CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]] // CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_INT_BB:.*]], label %[[CATCH_FALLTHROUGH_BB:.*]] @@ -51,7 +51,7 @@ void test0() { // CHECK-NEXT: br label %[[TRY_CONT_BB:.*]] // CHECK: [[CATCH_FALLTHROUGH_BB]] -// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(ptr @_ZTId) #7 +// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTId) #7 // CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]] // CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_FLOAT_BB:.*]], label %[[RETHROW_BB:.*]] diff --git a/llvm/examples/ExceptionDemo/ExceptionDemo.cpp b/llvm/examples/ExceptionDemo/ExceptionDemo.cpp index 0afc6b30d140..fdee76cb9614 100644 --- a/llvm/examples/ExceptionDemo/ExceptionDemo.cpp +++ b/llvm/examples/ExceptionDemo/ExceptionDemo.cpp @@ -1865,7 +1865,7 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos, // llvm.eh.typeid.for intrinsic - getDeclaration(&module, llvm::Intrinsic::eh_typeid_for); + getDeclaration(&module, llvm::Intrinsic::eh_typeid_for, builder.getPtrTy()); } diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index 78f0dbec863e..3019f68083d4 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1371,7 +1371,7 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in { // The result of eh.typeid.for depends on the enclosing function, but inside a // given function it is 'const' and may be CSE'd etc. -def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; +def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty], [IntrNoMem]>; def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>; def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>; @@ -1730,7 +1730,7 @@ def int_coro_subfn_addr : DefaultAttrsIntrinsic< ///===-------------------------- Other Intrinsics --------------------------===// // -// TODO: We should introduce a new memory kind fo traps (and other side effects +// TODO: We should introduce a new memory kind fo traps (and other side effects // we only model to keep things alive). def int_trap : Intrinsic<[], [], [IntrNoReturn, IntrCold, IntrInaccessibleMemOnly, IntrWriteMem]>, ClangBuiltin<"__builtin_trap">; diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-exceptions.ll b/llvm/test/CodeGen/WebAssembly/lower-em-exceptions.ll index d17a5b419e35..f6b36c56c6d3 100644 --- a/llvm/test/CodeGen/WebAssembly/lower-em-exceptions.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-exceptions.ll @@ -44,7 +44,7 @@ lpad: ; preds = %entry ; CHECK-NEXT: %[[CDR:.*]] = extractvalue { ptr, i32 } %[[IVI2]], 1 catch.dispatch: ; preds = %lpad - %3 = call i32 @llvm.eh.typeid.for(ptr @_ZTIi) + %3 = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) %matches = icmp eq i32 %2, %3 br i1 %matches, label %catch1, label %catch ; CHECK: catch.dispatch: @@ -139,7 +139,7 @@ lpad: ; preds = %entry br label %catch.dispatch catch.dispatch: ; preds = %lpad - %4 = call i32 @llvm.eh.typeid.for(ptr @_ZTIi) + %4 = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) %matches = icmp eq i32 %3, %4 br i1 %matches, label %catch1, label %catch @@ -162,7 +162,7 @@ declare void @foo(i32) declare ptr @bar(i8, i8) declare i32 @__gxx_personality_v0(...) -declare i32 @llvm.eh.typeid.for(ptr) +declare i32 @llvm.eh.typeid.for.p0(ptr) declare ptr @__cxa_begin_catch(ptr) declare void @__cxa_end_catch() declare void @__cxa_call_unexpected(ptr) diff --git a/llvm/test/Transforms/GVNHoist/infinite-loop-indirect.ll b/llvm/test/Transforms/GVNHoist/infinite-loop-indirect.ll index aef55af81dca..a7e6ff30d8b2 100644 --- a/llvm/test/Transforms/GVNHoist/infinite-loop-indirect.ll +++ b/llvm/test/Transforms/GVNHoist/infinite-loop-indirect.ll @@ -292,7 +292,7 @@ define i32 @foo2(ptr nocapture readonly %i) local_unnamed_addr personality ptr @ ; CHECK-NEXT: [[BC1:%.*]] = add i32 [[TMP0]], 10 ; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP2]], 0 ; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { ptr, i32 } [[TMP2]], 1 -; CHECK-NEXT: [[TMP5:%.*]] = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIi) #[[ATTR1]] +; CHECK-NEXT: [[TMP5:%.*]] = tail call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) #[[ATTR1]] ; CHECK-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[TMP4]], [[TMP5]] ; CHECK-NEXT: [[BC7:%.*]] = add i32 [[TMP0]], 10 ; CHECK-NEXT: [[TMP6:%.*]] = tail call ptr @__cxa_begin_catch(ptr [[TMP3]]) #[[ATTR1]] @@ -340,7 +340,7 @@ lpad: %bc1 = add i32 %0, 10 %3 = extractvalue { ptr, i32 } %2, 0 %4 = extractvalue { ptr, i32 } %2, 1 - %5 = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIi) #2 + %5 = tail call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) #2 %matches = icmp eq i32 %4, %5 %bc7 = add i32 %0, 10 %6 = tail call ptr @__cxa_begin_catch(ptr %3) #2 @@ -383,7 +383,7 @@ declare void @__cxa_throw(ptr, ptr, ptr) local_unnamed_addr declare i32 @__gxx_personality_v0(...) ; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(ptr) #1 +declare i32 @llvm.eh.typeid.for.p0(ptr) #1 declare ptr @__cxa_begin_catch(ptr) local_unnamed_addr diff --git a/llvm/test/Transforms/Inline/inline_invoke.ll b/llvm/test/Transforms/Inline/inline_invoke.ll index 89c56447c07b..5441e2a9e63b 100644 --- a/llvm/test/Transforms/Inline/inline_invoke.ll +++ b/llvm/test/Transforms/Inline/inline_invoke.ll @@ -19,7 +19,7 @@ declare void @use(i32) nounwind declare void @opaque() -declare i32 @llvm.eh.typeid.for(ptr) nounwind +declare i32 @llvm.eh.typeid.for.p0(ptr) nounwind declare i32 @__gxx_personality_v0(...) @@ -74,7 +74,7 @@ lpad: ; preds = %entry catch ptr @_ZTIi %eh.exc = extractvalue { ptr, i32 } %exn, 0 %eh.selector = extractvalue { ptr, i32 } %exn, 1 - %0 = call i32 @llvm.eh.typeid.for(ptr @_ZTIi) nounwind + %0 = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) nounwind %1 = icmp eq i32 %eh.selector, %0 br i1 %1, label %catch, label %eh.resume @@ -109,7 +109,7 @@ eh.resume: ; CHECK-NEXT: phi { ptr, i32 } [ ; CHECK-NEXT: extractvalue { ptr, i32 } ; CHECK-NEXT: extractvalue { ptr, i32 } -; CHECK-NEXT: call i32 @llvm.eh.typeid.for( +; CHECK-NEXT: call i32 @llvm.eh.typeid.for.p0( ;; Test 1 - Correctly handle phis in outer landing pads. @@ -133,7 +133,7 @@ lpad: catch ptr @_ZTIi %eh.exc = extractvalue { ptr, i32 } %exn, 0 %eh.selector = extractvalue { ptr, i32 } %exn, 1 - %0 = call i32 @llvm.eh.typeid.for(ptr @_ZTIi) nounwind + %0 = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) nounwind %1 = icmp eq i32 %eh.selector, %0 br i1 %1, label %catch, label %eh.resume @@ -212,7 +212,7 @@ eh.resume: ; CHECK-NEXT: [[EXNJ1:%.*]] = phi { ptr, i32 } [ [[EXNJ2]], %[[LPAD_JOIN2]] ], [ [[LPADVAL1]], %[[RESUME1]] ] ; CHECK-NEXT: extractvalue { ptr, i32 } [[EXNJ1]], 0 ; CHECK-NEXT: [[SELJ1:%.*]] = extractvalue { ptr, i32 } [[EXNJ1]], 1 -; CHECK-NEXT: [[T:%.*]] = call i32 @llvm.eh.typeid.for( +; CHECK-NEXT: [[T:%.*]] = call i32 @llvm.eh.typeid.for.p0( ; CHECK-NEXT: icmp eq i32 [[SELJ1]], [[T]] ; CHECK: call void @use(i32 [[XJ1]]) diff --git a/llvm/test/Transforms/LICM/scalar-promote-unwind.ll b/llvm/test/Transforms/LICM/scalar-promote-unwind.ll index be11722d2d56..f7829c4d6e4d 100644 --- a/llvm/test/Transforms/LICM/scalar-promote-unwind.ll +++ b/llvm/test/Transforms/LICM/scalar-promote-unwind.ll @@ -304,7 +304,7 @@ define void @loop_within_tryblock() personality ptr @__gxx_personality_v0 { ; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1 ; CHECK-NEXT: br label [[CATCH_DISPATCH:%.*]] ; CHECK: catch.dispatch: -; CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for(ptr @_ZTIi) +; CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) ; CHECK-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[TMP2]], [[TMP3]] ; CHECK-NEXT: br i1 [[MATCHES]], label [[CATCH:%.*]], label [[EH_RESUME:%.*]] ; CHECK: catch: @@ -355,7 +355,7 @@ lpad: br label %catch.dispatch catch.dispatch: - %4 = call i32 @llvm.eh.typeid.for(ptr @_ZTIi) #3 + %4 = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) #3 %matches = icmp eq i32 %3, %4 br i1 %matches, label %catch, label %eh.resume @@ -564,6 +564,6 @@ declare ptr @__cxa_begin_catch(ptr) declare void @__cxa_end_catch() -declare i32 @llvm.eh.typeid.for(ptr) +declare i32 @llvm.eh.typeid.for.p0(ptr) declare void @f() uwtable diff --git a/llvm/test/Transforms/LowerTypeTests/cfi-unwind-direct-call.ll b/llvm/test/Transforms/LowerTypeTests/cfi-unwind-direct-call.ll index 3e1f8b97e98b..4d5055cc5a76 100644 --- a/llvm/test/Transforms/LowerTypeTests/cfi-unwind-direct-call.ll +++ b/llvm/test/Transforms/LowerTypeTests/cfi-unwind-direct-call.ll @@ -65,7 +65,7 @@ lpad: ; preds = %cfi.cont %1 = landingpad { ptr, i32 } catch ptr @_ZTIi %2 = extractvalue { ptr, i32 } %1, 1 - %3 = tail call i32 @llvm.eh.typeid.for(ptr nonnull @_ZTIi) #5 + %3 = tail call i32 @llvm.eh.typeid.for.p0(ptr nonnull @_ZTIi) #5 %matches = icmp eq i32 %2, %3 br i1 %matches, label %catch, label %eh.resume @@ -90,7 +90,7 @@ declare void @__cfi_slowpath(i64, ptr) local_unnamed_addr declare i32 @__gxx_personality_v0(...) ; Function Attrs: nofree nosync nounwind memory(none) -declare i32 @llvm.eh.typeid.for(ptr) #2 +declare i32 @llvm.eh.typeid.for.p0(ptr) #2 declare ptr @__cxa_begin_catch(ptr) local_unnamed_addr @@ -181,7 +181,7 @@ attributes #8 = { noreturn nounwind } ; CHECK-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 } ; CHECK-NEXT: catch ptr @_ZTIi ; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1 -; CHECK-NEXT: [[TMP2:%.*]] = tail call i32 @llvm.eh.typeid.for(ptr nonnull @_ZTIi) #[[ATTR6]] +; CHECK-NEXT: [[TMP2:%.*]] = tail call i32 @llvm.eh.typeid.for.p0(ptr nonnull @_ZTIi) #[[ATTR6]] ; CHECK-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[TMP1]], [[TMP2]] ; CHECK-NEXT: br i1 [[MATCHES]], label [[CATCH:%.*]], label [[EH_RESUME:%.*]] ; CHECK: catch: diff --git a/llvm/test/Transforms/NewGVN/2011-09-07-TypeIdFor.ll b/llvm/test/Transforms/NewGVN/2011-09-07-TypeIdFor.ll index 675e7da26a10..afd7610b7162 100644 --- a/llvm/test/Transforms/NewGVN/2011-09-07-TypeIdFor.ll +++ b/llvm/test/Transforms/NewGVN/2011-09-07-TypeIdFor.ll @@ -10,7 +10,7 @@ declare void @_Z4barv() declare void @_Z7cleanupv() -declare i32 @llvm.eh.typeid.for(ptr) nounwind readonly +declare i32 @llvm.eh.typeid.for.p0(ptr) nounwind readonly declare ptr @__cxa_begin_catch(ptr) nounwind @@ -32,11 +32,11 @@ define void @_Z3foov() uwtable personality ptr @__gxx_personality_v0 { ; CHECK-NEXT: catch ptr @_ZTIb ; CHECK-NEXT: [[EXC_PTR2_I:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0 ; CHECK-NEXT: [[FILTER3_I:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1 -; CHECK-NEXT: [[TYPEID_I:%.*]] = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIi) +; CHECK-NEXT: [[TYPEID_I:%.*]] = tail call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[FILTER3_I]], [[TYPEID_I]] ; CHECK-NEXT: br i1 [[TMP1]], label [[PPAD:%.*]], label [[NEXT:%.*]] ; CHECK: next: -; CHECK-NEXT: [[TYPEID1_I:%.*]] = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIb) +; CHECK-NEXT: [[TYPEID1_I:%.*]] = tail call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIb) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[FILTER3_I]], [[TYPEID1_I]] ; CHECK-NEXT: br i1 [[TMP2]], label [[PPAD2:%.*]], label [[NEXT2:%.*]] ; CHECK: ppad: @@ -77,12 +77,12 @@ lpad: ; preds = %entry catch ptr @_ZTIb %exc_ptr2.i = extractvalue { ptr, i32 } %0, 0 %filter3.i = extractvalue { ptr, i32 } %0, 1 - %typeid.i = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIi) + %typeid.i = tail call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) %1 = icmp eq i32 %filter3.i, %typeid.i br i1 %1, label %ppad, label %next next: ; preds = %lpad - %typeid1.i = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIb) + %typeid1.i = tail call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIb) %2 = icmp eq i32 %filter3.i, %typeid1.i br i1 %2, label %ppad2, label %next2 @@ -98,12 +98,12 @@ ppad2: ; preds = %next next2: ; preds = %next call void @_Z7cleanupv() - %typeid = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIi) + %typeid = tail call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) %4 = icmp eq i32 %filter3.i, %typeid br i1 %4, label %ppad3, label %next3 next3: ; preds = %next2 - %typeid1 = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIb) + %typeid1 = tail call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIb) %5 = icmp eq i32 %filter3.i, %typeid1 br i1 %5, label %ppad4, label %unwind diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td index bd347d0cf630..57af89f5dbf8 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td @@ -635,7 +635,7 @@ def LLVM_VaEndOp : LLVM_ZeroResultIntrOp<"vaend", [0]>, // Exception handling intrinsics. // -def LLVM_EhTypeidForOp : LLVM_OneResultIntrOp<"eh.typeid.for"> { +def LLVM_EhTypeidForOp : LLVM_OneResultIntrOp<"eh.typeid.for", [], [0]> { let arguments = (ins LLVM_AnyPointer:$type_info); let assemblyFormat = "$type_info attr-dict `:` functional-type(operands, results)"; } diff --git a/mlir/test/Target/LLVMIR/Import/intrinsic.ll b/mlir/test/Target/LLVMIR/Import/intrinsic.ll index e43024ff868e..9a5528002ef5 100644 --- a/mlir/test/Target/LLVMIR/Import/intrinsic.ll +++ b/mlir/test/Target/LLVMIR/Import/intrinsic.ll @@ -732,7 +732,7 @@ define void @coro_promise(ptr %0, i32 %1, i1 %2) { ; CHECK-LABEL: llvm.func @eh_typeid_for define void @eh_typeid_for(ptr %0) { ; CHECK: llvm.intr.eh.typeid.for %{{.*}} : (!llvm.ptr) -> i32 - %2 = call i32 @llvm.eh.typeid.for(ptr %0) + %2 = call i32 @llvm.eh.typeid.for.p0(ptr %0) ret void } @@ -1082,7 +1082,7 @@ declare i1 @llvm.coro.end(ptr, i1, token) declare ptr @llvm.coro.free(token, ptr nocapture readonly) declare void @llvm.coro.resume(ptr) declare ptr @llvm.coro.promise(ptr nocapture, i32, i1) -declare i32 @llvm.eh.typeid.for(ptr) +declare i32 @llvm.eh.typeid.for.p0(ptr) declare ptr @llvm.stacksave.p0() declare ptr addrspace(1) @llvm.stacksave.p1() declare void @llvm.stackrestore.p0(ptr) diff --git a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir index 238c3e4263cb..1e533aeacfb4 100644 --- a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir +++ b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir @@ -724,7 +724,7 @@ llvm.func @coro_promise(%arg0: !llvm.ptr, %arg1 : i32, %arg2 : i1) { // CHECK-LABEL: @eh_typeid_for llvm.func @eh_typeid_for(%arg0 : !llvm.ptr) { - // CHECK: call i32 @llvm.eh.typeid.for + // CHECK: call i32 @llvm.eh.typeid.for.p0 %0 = llvm.intr.eh.typeid.for %arg0 : (!llvm.ptr) -> i32 llvm.return } -- GitLab From 0c7d268ba72767b70c7bf0bc8ae6422c509f94d8 Mon Sep 17 00:00:00 2001 From: aengelke Date: Sun, 19 May 2024 16:38:53 +0200 Subject: [PATCH 026/793] [CodeGen][SDAG] Skip preferred extend at O0 (#92643) This is a pure optimization to avoid redundant extensions, but iterating over all users is expensive, so don't do this at -O0. --- llvm/include/llvm/CodeGen/SelectionDAG.h | 1 + llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h index 979ef8033eb5..ed6962685f7b 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -469,6 +469,7 @@ public: MachineFunction &getMachineFunction() const { return *MF; } const Pass *getPass() const { return SDAGISelPass; } + CodeGenOptLevel getOptLevel() const { return OptLevel; } const DataLayout &getDataLayout() const { return MF->getDataLayout(); } const TargetMachine &getTarget() const { return TM; } const TargetSubtargetInfo &getSubtarget() const { return MF->getSubtarget(); } diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index 8fb6b11b8805..35f840201e4b 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -222,8 +222,10 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, if (!isa(I) || !StaticAllocaMap.count(cast(&I))) InitializeRegForValue(&I); - // Decide the preferred extend type for a value. - PreferredExtendType[&I] = getPreferredExtendForValue(&I); + // Decide the preferred extend type for a value. This iterates over all + // users and therefore isn't cheap, so don't do this at O0. + if (DAG->getOptLevel() != CodeGenOptLevel::None) + PreferredExtendType[&I] = getPreferredExtendForValue(&I); } } -- GitLab From 9e4ef0dee18c0c99325e8d56f16c149020e89d37 Mon Sep 17 00:00:00 2001 From: aengelke Date: Sun, 19 May 2024 16:39:19 +0200 Subject: [PATCH 027/793] [CodeGen][SDAG] Track returntwice in lowering info (#92640) This saves an extra iteration over the all instructions of the function. --- llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp | 4 ++++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index 35f840201e4b..de22d230b1c3 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -214,6 +214,10 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, if (CI->isMustTailCall() && Fn->isVarArg()) MF->getFrameInfo().setHasMustTailInVarArgFunc(true); } + + // Determine if there is a call to setjmp in the machine function. + if (Call->hasFnAttr(Attribute::ReturnsTwice)) + MF->setExposesReturnsTwice(true); } // Mark values used outside their block as exported, by allocating diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index b5694c955b8c..8addaf1ae3e5 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -680,9 +680,6 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { } } - // Determine if there is a call to setjmp in the machine function. - MF->setExposesReturnsTwice(Fn.callsFunctionThatReturnsTwice()); - // Determine if floating point is used for msvc computeUsesMSVCFloatingPoint(TM.getTargetTriple(), Fn, MF->getMMI()); -- GitLab From eab92cb7f33be16a6a17549182e9237112b7a183 Mon Sep 17 00:00:00 2001 From: Nhat Nguyen Date: Sun, 19 May 2024 10:57:11 -0400 Subject: [PATCH 028/793] [llvm] Add KnownBits implementations for avgFloor and avgCeil (#86445) This PR is to address the issue #84640 --- llvm/include/llvm/Support/KnownBits.h | 12 +++++++ .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 29 +++++++++++------ llvm/lib/Support/KnownBits.cpp | 31 +++++++++++++++++++ llvm/unittests/Support/KnownBitsTest.cpp | 12 +++++++ 4 files changed, 74 insertions(+), 10 deletions(-) diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h index 9b7f405b6256..ba4a5f01036c 100644 --- a/llvm/include/llvm/Support/KnownBits.h +++ b/llvm/include/llvm/Support/KnownBits.h @@ -354,6 +354,18 @@ public: /// Compute knownbits resulting from llvm.usub.sat(LHS, RHS) static KnownBits usub_sat(const KnownBits &LHS, const KnownBits &RHS); + /// Compute knownbits resulting from APIntOps::avgFloorS + static KnownBits avgFloorS(const KnownBits &LHS, const KnownBits &RHS); + + /// Compute knownbits resulting from APIntOps::avgFloorU + static KnownBits avgFloorU(const KnownBits &LHS, const KnownBits &RHS); + + /// Compute knownbits resulting from APIntOps::avgCeilS + static KnownBits avgCeilS(const KnownBits &LHS, const KnownBits &RHS); + + /// Compute knownbits resulting from APIntOps::avgCeilU + static KnownBits avgCeilU(const KnownBits &LHS, const KnownBits &RHS); + /// Compute known bits resulting from multiplying LHS and RHS. static KnownBits mul(const KnownBits &LHS, const KnownBits &RHS, bool NoUndefSelfMultiply = false); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 2e1f4b7e5b37..72685a2d7721 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -3468,19 +3468,28 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts, Known = KnownBits::mulhs(Known, Known2); break; } - case ISD::AVGFLOORU: - case ISD::AVGCEILU: - case ISD::AVGFLOORS: + case ISD::AVGFLOORU: { + Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); + Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); + Known = KnownBits::avgFloorU(Known, Known2); + break; + } + case ISD::AVGCEILU: { + Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); + Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); + Known = KnownBits::avgCeilU(Known, Known2); + break; + } + case ISD::AVGFLOORS: { + Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); + Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); + Known = KnownBits::avgFloorS(Known, Known2); + break; + } case ISD::AVGCEILS: { - bool IsCeil = Opcode == ISD::AVGCEILU || Opcode == ISD::AVGCEILS; - bool IsSigned = Opcode == ISD::AVGFLOORS || Opcode == ISD::AVGCEILS; Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); - Known = IsSigned ? Known.sext(BitWidth + 1) : Known.zext(BitWidth + 1); - Known2 = IsSigned ? Known2.sext(BitWidth + 1) : Known2.zext(BitWidth + 1); - KnownBits Carry = KnownBits::makeConstant(APInt(1, IsCeil ? 1 : 0)); - Known = KnownBits::computeForAddCarry(Known, Known2, Carry); - Known = Known.extractBits(BitWidth, 1); + Known = KnownBits::avgCeilS(Known, Known2); break; } case ISD::SELECT: diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp index fe47884f3e55..d6012a8eea8a 100644 --- a/llvm/lib/Support/KnownBits.cpp +++ b/llvm/lib/Support/KnownBits.cpp @@ -774,6 +774,37 @@ KnownBits KnownBits::usub_sat(const KnownBits &LHS, const KnownBits &RHS) { return computeForSatAddSub(/*Add*/ false, /*Signed*/ false, LHS, RHS); } +static KnownBits avgCompute(KnownBits LHS, KnownBits RHS, bool IsCeil, + bool IsSigned) { + unsigned BitWidth = LHS.getBitWidth(); + LHS = IsSigned ? LHS.sext(BitWidth + 1) : LHS.zext(BitWidth + 1); + RHS = IsSigned ? RHS.sext(BitWidth + 1) : RHS.zext(BitWidth + 1); + KnownBits Carry = KnownBits::makeConstant(APInt(1, IsCeil ? 1 : 0)); + LHS = KnownBits::computeForAddCarry(LHS, RHS, Carry); + LHS = LHS.extractBits(BitWidth, 1); + return LHS; +} + +KnownBits KnownBits::avgFloorS(const KnownBits &LHS, const KnownBits &RHS) { + return avgCompute(LHS, RHS, /* IsCeil */ false, + /* IsSigned */ true); +} + +KnownBits KnownBits::avgFloorU(const KnownBits &LHS, const KnownBits &RHS) { + return avgCompute(LHS, RHS, /* IsCeil */ false, + /* IsSigned */ false); +} + +KnownBits KnownBits::avgCeilS(const KnownBits &LHS, const KnownBits &RHS) { + return avgCompute(LHS, RHS, /* IsCeil */ true, + /* IsSigned */ true); +} + +KnownBits KnownBits::avgCeilU(const KnownBits &LHS, const KnownBits &RHS) { + return avgCompute(LHS, RHS, /* IsCeil */ true, + /* IsSigned */ false); +} + KnownBits KnownBits::mul(const KnownBits &LHS, const KnownBits &RHS, bool NoUndefSelfMultiply) { unsigned BitWidth = LHS.getBitWidth(); diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp index d74070702716..824cf7501fd4 100644 --- a/llvm/unittests/Support/KnownBitsTest.cpp +++ b/llvm/unittests/Support/KnownBitsTest.cpp @@ -501,6 +501,18 @@ TEST(KnownBitsTest, BinaryExhaustive) { "mulhu", KnownBits::mulhu, [](const APInt &N1, const APInt &N2) { return APIntOps::mulhu(N1, N2); }, /*CheckOptimality=*/false); + + testBinaryOpExhaustive("avgFloorS", KnownBits::avgFloorS, APIntOps::avgFloorS, + false); + + testBinaryOpExhaustive("avgFloorU", KnownBits::avgFloorU, APIntOps::avgFloorU, + false); + + testBinaryOpExhaustive("avgCeilU", KnownBits::avgCeilU, APIntOps::avgCeilU, + false); + + testBinaryOpExhaustive("avgCeilS", KnownBits::avgCeilS, APIntOps::avgCeilS, + false); } TEST(KnownBitsTest, UnaryExhaustive) { -- GitLab From c1c1567d60983298a0db0efefd78899985464f19 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sun, 19 May 2024 17:35:42 +0200 Subject: [PATCH 029/793] SimplifyLibCalls: Permit pow(2, x) -> ldexp(1, x) fold for vectors (#92532) --- .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 7 +- .../Transforms/InstCombine/pow-to-ldexp.ll | 69 ++++++------------- 2 files changed, 24 insertions(+), 52 deletions(-) diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index c9567b740026..eb1224abf00e 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -2087,15 +2087,16 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) { AttributeList NoAttrs; // Attributes are only meaningful on the original call + const bool UseIntrinsic = Pow->doesNotAccessMemory(); + // pow(2.0, itofp(x)) -> ldexp(1.0, x) - // TODO: This does not work for vectors because there is no ldexp intrinsic. - if (!Ty->isVectorTy() && match(Base, m_SpecificFP(2.0)) && + if ((UseIntrinsic || !Ty->isVectorTy()) && match(Base, m_SpecificFP(2.0)) && (isa(Expo) || isa(Expo)) && hasFloatFn(M, TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) { if (Value *ExpoI = getIntToFPVal(Expo, B, TLI->getIntSize())) { Constant *One = ConstantFP::get(Ty, 1.0); - if (Pow->doesNotAccessMemory()) { + if (UseIntrinsic) { return copyFlags(*Pow, B.CreateIntrinsic(Intrinsic::ldexp, {Ty, ExpoI->getType()}, {One, ExpoI}, Pow, "exp2")); diff --git a/llvm/test/Transforms/InstCombine/pow-to-ldexp.ll b/llvm/test/Transforms/InstCombine/pow-to-ldexp.ll index 27249dd5d72a..b61f8809bd25 100644 --- a/llvm/test/Transforms/InstCombine/pow-to-ldexp.ll +++ b/llvm/test/Transforms/InstCombine/pow-to-ldexp.ll @@ -144,16 +144,10 @@ define half @pow_sitofp_f16_const_base_2(i32 %x) { } define <2 x float> @pow_sitofp_v2f32_const_base_2(<2 x i32> %x) { -; LDEXP-EXP2-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2( -; LDEXP-EXP2-SAME: <2 x i32> [[X:%.*]]) { -; LDEXP-EXP2-NEXT: [[EXP2:%.*]] = tail call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> , <2 x i32> [[X]]) -; LDEXP-EXP2-NEXT: ret <2 x float> [[EXP2]] -; -; LDEXP-NOEXP2-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2( -; LDEXP-NOEXP2-SAME: <2 x i32> [[X:%.*]]) { -; LDEXP-NOEXP2-NEXT: [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x float> -; LDEXP-NOEXP2-NEXT: [[POW:%.*]] = tail call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[ITOFP]]) -; LDEXP-NOEXP2-NEXT: ret <2 x float> [[POW]] +; LDEXP-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2( +; LDEXP-SAME: <2 x i32> [[X:%.*]]) { +; LDEXP-NEXT: [[EXP2:%.*]] = tail call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> , <2 x i32> [[X]]) +; LDEXP-NEXT: ret <2 x float> [[EXP2]] ; ; NOLDEXP-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2( ; NOLDEXP-SAME: <2 x i32> [[X:%.*]]) { @@ -205,15 +199,10 @@ define <2 x float> @pow_sitofp_v2f32_const_base_mixed_2(<2 x i32> %x) { } define <2 x float> @pow_sitofp_v2f32_const_base_2__flags(<2 x i32> %x) { -; LDEXP-EXP2-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2__flags( -; LDEXP-EXP2-SAME: <2 x i32> [[X:%.*]]) { -; LDEXP-EXP2-NEXT: [[EXP2:%.*]] = tail call nsz afn <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> , <2 x i32> [[X]]) -; LDEXP-EXP2-NEXT: ret <2 x float> [[EXP2]] -; -; LDEXP-NOEXP2-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2__flags( -; LDEXP-NOEXP2-SAME: <2 x i32> [[X:%.*]]) { -; LDEXP-NOEXP2-NEXT: [[POW:%.*]] = tail call nsz afn <2 x float> @llvm.powi.v2f32.v2i32(<2 x float> , <2 x i32> [[X]]) -; LDEXP-NOEXP2-NEXT: ret <2 x float> [[POW]] +; LDEXP-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2__flags( +; LDEXP-SAME: <2 x i32> [[X:%.*]]) { +; LDEXP-NEXT: [[EXP2:%.*]] = tail call nsz afn <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> , <2 x i32> [[X]]) +; LDEXP-NEXT: ret <2 x float> [[EXP2]] ; ; NOLDEXP-LABEL: define <2 x float> @pow_sitofp_v2f32_const_base_2__flags( ; NOLDEXP-SAME: <2 x i32> [[X:%.*]]) { @@ -227,16 +216,10 @@ define <2 x float> @pow_sitofp_v2f32_const_base_2__flags(<2 x i32> %x) { } define @pow_sitofp_nxv4f32_const_base_2( %x) { -; LDEXP-EXP2-LABEL: define @pow_sitofp_nxv4f32_const_base_2( -; LDEXP-EXP2-SAME: [[X:%.*]]) { -; LDEXP-EXP2-NEXT: [[EXP2:%.*]] = tail call @llvm.ldexp.nxv4f32.nxv4i32( shufflevector ( insertelement ( poison, float 1.000000e+00, i64 0), poison, zeroinitializer), [[X]]) -; LDEXP-EXP2-NEXT: ret [[EXP2]] -; -; LDEXP-NOEXP2-LABEL: define @pow_sitofp_nxv4f32_const_base_2( -; LDEXP-NOEXP2-SAME: [[X:%.*]]) { -; LDEXP-NOEXP2-NEXT: [[ITOFP:%.*]] = sitofp [[X]] to -; LDEXP-NOEXP2-NEXT: [[POW:%.*]] = tail call @llvm.pow.nxv4f32( shufflevector ( insertelement ( poison, float 2.000000e+00, i64 0), poison, zeroinitializer), [[ITOFP]]) -; LDEXP-NOEXP2-NEXT: ret [[POW]] +; LDEXP-LABEL: define @pow_sitofp_nxv4f32_const_base_2( +; LDEXP-SAME: [[X:%.*]]) { +; LDEXP-NEXT: [[EXP2:%.*]] = tail call @llvm.ldexp.nxv4f32.nxv4i32( shufflevector ( insertelement ( poison, float 1.000000e+00, i64 0), poison, zeroinitializer), [[X]]) +; LDEXP-NEXT: ret [[EXP2]] ; ; NOLDEXP-LABEL: define @pow_sitofp_nxv4f32_const_base_2( ; NOLDEXP-SAME: [[X:%.*]]) { @@ -250,16 +233,10 @@ define @pow_sitofp_nxv4f32_const_base_2( } define <2 x half> @pow_sitofp_v2f16_const_base_2(<2 x i32> %x) { -; LDEXP-EXP2-LABEL: define <2 x half> @pow_sitofp_v2f16_const_base_2( -; LDEXP-EXP2-SAME: <2 x i32> [[X:%.*]]) { -; LDEXP-EXP2-NEXT: [[EXP2:%.*]] = tail call <2 x half> @llvm.ldexp.v2f16.v2i32(<2 x half> , <2 x i32> [[X]]) -; LDEXP-EXP2-NEXT: ret <2 x half> [[EXP2]] -; -; LDEXP-NOEXP2-LABEL: define <2 x half> @pow_sitofp_v2f16_const_base_2( -; LDEXP-NOEXP2-SAME: <2 x i32> [[X:%.*]]) { -; LDEXP-NOEXP2-NEXT: [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x half> -; LDEXP-NOEXP2-NEXT: [[POW:%.*]] = tail call <2 x half> @llvm.pow.v2f16(<2 x half> , <2 x half> [[ITOFP]]) -; LDEXP-NOEXP2-NEXT: ret <2 x half> [[POW]] +; LDEXP-LABEL: define <2 x half> @pow_sitofp_v2f16_const_base_2( +; LDEXP-SAME: <2 x i32> [[X:%.*]]) { +; LDEXP-NEXT: [[EXP2:%.*]] = tail call <2 x half> @llvm.ldexp.v2f16.v2i32(<2 x half> , <2 x i32> [[X]]) +; LDEXP-NEXT: ret <2 x half> [[EXP2]] ; ; NOLDEXP-LABEL: define <2 x half> @pow_sitofp_v2f16_const_base_2( ; NOLDEXP-SAME: <2 x i32> [[X:%.*]]) { @@ -273,16 +250,10 @@ define <2 x half> @pow_sitofp_v2f16_const_base_2(<2 x i32> %x) { } define <2 x double> @pow_sitofp_v2f64_const_base_2(<2 x i32> %x) { -; LDEXP-EXP2-LABEL: define <2 x double> @pow_sitofp_v2f64_const_base_2( -; LDEXP-EXP2-SAME: <2 x i32> [[X:%.*]]) { -; LDEXP-EXP2-NEXT: [[EXP2:%.*]] = tail call <2 x double> @llvm.ldexp.v2f64.v2i32(<2 x double> , <2 x i32> [[X]]) -; LDEXP-EXP2-NEXT: ret <2 x double> [[EXP2]] -; -; LDEXP-NOEXP2-LABEL: define <2 x double> @pow_sitofp_v2f64_const_base_2( -; LDEXP-NOEXP2-SAME: <2 x i32> [[X:%.*]]) { -; LDEXP-NOEXP2-NEXT: [[ITOFP:%.*]] = sitofp <2 x i32> [[X]] to <2 x double> -; LDEXP-NOEXP2-NEXT: [[POW:%.*]] = tail call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> [[ITOFP]]) -; LDEXP-NOEXP2-NEXT: ret <2 x double> [[POW]] +; LDEXP-LABEL: define <2 x double> @pow_sitofp_v2f64_const_base_2( +; LDEXP-SAME: <2 x i32> [[X:%.*]]) { +; LDEXP-NEXT: [[EXP2:%.*]] = tail call <2 x double> @llvm.ldexp.v2f64.v2i32(<2 x double> , <2 x i32> [[X]]) +; LDEXP-NEXT: ret <2 x double> [[EXP2]] ; ; NOLDEXP-LABEL: define <2 x double> @pow_sitofp_v2f64_const_base_2( ; NOLDEXP-SAME: <2 x i32> [[X:%.*]]) { -- GitLab From b050048d35f6580fb427e6de9063444aa85625c6 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sun, 19 May 2024 16:45:23 +0100 Subject: [PATCH 030/793] [VPlan] Simplify (X && Y) || (X && !Y) -> X. (#89386) Simplify a common pattern generated for masks when folding the tail. PR: https://github.com/llvm/llvm-project/pull/89386 --- .../Transforms/Vectorize/VPlanPatternMatch.h | 8 +++++++- .../Transforms/Vectorize/VPlanTransforms.cpp | 15 +++++++++++++- .../LoopVectorize/AArch64/masked-call.ll | 9 +++------ .../AArch64/scalable-strict-fadd.ll | 3 +-- .../LoopVectorize/RISCV/uniform-load-store.ll | 20 ++++--------------- .../Transforms/LoopVectorize/uniform-blend.ll | 5 +---- .../unused-blend-mask-for-first-operand.ll | 12 ++--------- .../vplan-sink-scalars-and-merge.ll | 19 +++++------------- 8 files changed, 37 insertions(+), 54 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h index 50b08bbb7ebf..56cbaa420129 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h +++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h @@ -270,9 +270,15 @@ m_Mul(const Op0_t &Op0, const Op1_t &Op1) { template inline AllBinaryRecipe_match -m_Or(const Op0_t &Op0, const Op1_t &Op1) { +m_BinaryOr(const Op0_t &Op0, const Op1_t &Op1) { return m_Binary(Op0, Op1); } + +template +inline BinaryVPInstruction_match +m_LogicalAnd(const Op0_t &Op0, const Op1_t &Op1) { + return m_VPInstruction(Op0, Op1); +} } // namespace VPlanPatternMatch } // namespace llvm diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp index c0eb6d710ad3..4c968c2834b1 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp @@ -935,6 +935,19 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) { #endif } + // Simplify (X && Y) || (X && !Y) -> X. + // TODO: Split up into simpler, modular combines: (X && Y) || (X && Z) into X + // && (Y || Z) and (X || !X) into true. This requires queuing newly created + // recipes to be visited during simplification. + VPValue *X, *Y, *X1, *Y1; + if (match(&R, + m_BinaryOr(m_LogicalAnd(m_VPValue(X), m_VPValue(Y)), + m_LogicalAnd(m_VPValue(X1), m_Not(m_VPValue(Y1))))) && + X == X1 && Y == Y1) { + R.getVPSingleValue()->replaceAllUsesWith(X); + return; + } + if (match(&R, m_CombineOr(m_Mul(m_VPValue(A), m_SpecificInt(1)), m_Mul(m_SpecificInt(1), m_VPValue(A))))) return R.getVPSingleValue()->replaceAllUsesWith(A); @@ -1402,7 +1415,7 @@ void VPlanTransforms::dropPoisonGeneratingRecipes( // for dependence analysis). Instead, replace it with an equivalent Add. // This is possible as all users of the disjoint OR only access lanes // where the operands are disjoint or poison otherwise. - if (match(RecWithFlags, m_Or(m_VPValue(A), m_VPValue(B))) && + if (match(RecWithFlags, m_BinaryOr(m_VPValue(A), m_VPValue(B))) && RecWithFlags->isDisjoint()) { VPBuilder Builder(RecWithFlags); VPInstruction *New = Builder.createOverflowingOp( diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/masked-call.ll b/llvm/test/Transforms/LoopVectorize/AArch64/masked-call.ll index b91579106261..d335ac4b6970 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/masked-call.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/masked-call.ll @@ -223,10 +223,9 @@ define void @test_if_then(ptr noalias %a, ptr readnone %b) #4 { ; TFCOMMON-NEXT: [[TMP10:%.*]] = call @foo_vector( [[WIDE_MASKED_LOAD]], [[TMP9]]) ; TFCOMMON-NEXT: [[TMP11:%.*]] = xor [[TMP8]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer) ; TFCOMMON-NEXT: [[TMP12:%.*]] = select [[ACTIVE_LANE_MASK]], [[TMP11]], zeroinitializer -; TFCOMMON-NEXT: [[TMP13:%.*]] = or [[TMP9]], [[TMP12]] ; TFCOMMON-NEXT: [[PREDPHI:%.*]] = select [[TMP12]], zeroinitializer, [[TMP10]] ; TFCOMMON-NEXT: [[TMP14:%.*]] = getelementptr inbounds i64, ptr [[B:%.*]], i64 [[INDEX]] -; TFCOMMON-NEXT: call void @llvm.masked.store.nxv2i64.p0( [[PREDPHI]], ptr [[TMP14]], i32 8, [[TMP13]]) +; TFCOMMON-NEXT: call void @llvm.masked.store.nxv2i64.p0( [[PREDPHI]], ptr [[TMP14]], i32 8, [[ACTIVE_LANE_MASK]]) ; TFCOMMON-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], [[TMP6]] ; TFCOMMON-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call @llvm.get.active.lane.mask.nxv2i1.i64(i64 [[INDEX_NEXT]], i64 1025) ; TFCOMMON-NEXT: [[TMP15:%.*]] = xor [[ACTIVE_LANE_MASK_NEXT]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer) @@ -272,16 +271,14 @@ define void @test_if_then(ptr noalias %a, ptr readnone %b) #4 { ; TFA_INTERLEAVE-NEXT: [[TMP20:%.*]] = xor [[TMP14]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer) ; TFA_INTERLEAVE-NEXT: [[TMP21:%.*]] = select [[ACTIVE_LANE_MASK]], [[TMP19]], zeroinitializer ; TFA_INTERLEAVE-NEXT: [[TMP22:%.*]] = select [[ACTIVE_LANE_MASK2]], [[TMP20]], zeroinitializer -; TFA_INTERLEAVE-NEXT: [[TMP23:%.*]] = or [[TMP15]], [[TMP21]] -; TFA_INTERLEAVE-NEXT: [[TMP24:%.*]] = or [[TMP16]], [[TMP22]] ; TFA_INTERLEAVE-NEXT: [[PREDPHI:%.*]] = select [[TMP21]], zeroinitializer, [[TMP17]] ; TFA_INTERLEAVE-NEXT: [[PREDPHI4:%.*]] = select [[TMP22]], zeroinitializer, [[TMP18]] ; TFA_INTERLEAVE-NEXT: [[TMP25:%.*]] = getelementptr inbounds i64, ptr [[B:%.*]], i64 [[INDEX]] ; TFA_INTERLEAVE-NEXT: [[TMP26:%.*]] = call i64 @llvm.vscale.i64() ; TFA_INTERLEAVE-NEXT: [[TMP27:%.*]] = mul i64 [[TMP26]], 2 ; TFA_INTERLEAVE-NEXT: [[TMP28:%.*]] = getelementptr inbounds i64, ptr [[TMP25]], i64 [[TMP27]] -; TFA_INTERLEAVE-NEXT: call void @llvm.masked.store.nxv2i64.p0( [[PREDPHI]], ptr [[TMP25]], i32 8, [[TMP23]]) -; TFA_INTERLEAVE-NEXT: call void @llvm.masked.store.nxv2i64.p0( [[PREDPHI4]], ptr [[TMP28]], i32 8, [[TMP24]]) +; TFA_INTERLEAVE-NEXT: call void @llvm.masked.store.nxv2i64.p0( [[PREDPHI]], ptr [[TMP25]], i32 8, [[ACTIVE_LANE_MASK]]) +; TFA_INTERLEAVE-NEXT: call void @llvm.masked.store.nxv2i64.p0( [[PREDPHI4]], ptr [[TMP28]], i32 8, [[ACTIVE_LANE_MASK2]]) ; TFA_INTERLEAVE-NEXT: [[INDEX_NEXT:%.*]] = add i64 [[INDEX]], [[TMP6]] ; TFA_INTERLEAVE-NEXT: [[TMP29:%.*]] = call i64 @llvm.vscale.i64() ; TFA_INTERLEAVE-NEXT: [[TMP30:%.*]] = mul i64 [[TMP29]], 2 diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/scalable-strict-fadd.ll b/llvm/test/Transforms/LoopVectorize/AArch64/scalable-strict-fadd.ll index ddc004657ed5..bcf8096f1b73 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/scalable-strict-fadd.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/scalable-strict-fadd.ll @@ -1241,9 +1241,8 @@ define float @fadd_conditional(ptr noalias nocapture readonly %a, ptr noalias no ; CHECK-ORDERED-TF-NEXT: [[WIDE_MASKED_LOAD1:%.*]] = call @llvm.masked.load.nxv4f32.p0(ptr [[TMP16]], i32 4, [[TMP15]], poison) ; CHECK-ORDERED-TF-NEXT: [[TMP17:%.*]] = xor [[TMP13]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer) ; CHECK-ORDERED-TF-NEXT: [[TMP18:%.*]] = select [[ACTIVE_LANE_MASK]], [[TMP17]], zeroinitializer -; CHECK-ORDERED-TF-NEXT: [[TMP19:%.*]] = or [[TMP15]], [[TMP18]] ; CHECK-ORDERED-TF-NEXT: [[PREDPHI:%.*]] = select [[TMP18]], shufflevector ( insertelement ( poison, float 3.000000e+00, i64 0), poison, zeroinitializer), [[WIDE_MASKED_LOAD1]] -; CHECK-ORDERED-TF-NEXT: [[TMP20:%.*]] = select [[TMP19]], [[PREDPHI]], shufflevector ( insertelement ( poison, float -0.000000e+00, i64 0), poison, zeroinitializer) +; CHECK-ORDERED-TF-NEXT: [[TMP20:%.*]] = select [[ACTIVE_LANE_MASK]], [[PREDPHI]], shufflevector ( insertelement ( poison, float -0.000000e+00, i64 0), poison, zeroinitializer) ; CHECK-ORDERED-TF-NEXT: [[TMP21]] = call float @llvm.vector.reduce.fadd.nxv4f32(float [[VEC_PHI]], [[TMP20]]) ; CHECK-ORDERED-TF-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], [[TMP23]] ; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[INDEX]], i64 [[TMP9]]) diff --git a/llvm/test/Transforms/LoopVectorize/RISCV/uniform-load-store.ll b/llvm/test/Transforms/LoopVectorize/RISCV/uniform-load-store.ll index 1ce4cb928e80..ee70f4aa3585 100644 --- a/llvm/test/Transforms/LoopVectorize/RISCV/uniform-load-store.ll +++ b/llvm/test/Transforms/LoopVectorize/RISCV/uniform-load-store.ll @@ -462,13 +462,10 @@ define void @conditional_uniform_load(ptr noalias nocapture %a, ptr noalias noca ; TF-SCALABLE-NEXT: [[TMP12:%.*]] = icmp ugt [[VEC_IND]], shufflevector ( insertelement ( poison, i64 10, i64 0), poison, zeroinitializer) ; TF-SCALABLE-NEXT: [[TMP13:%.*]] = select [[ACTIVE_LANE_MASK]], [[TMP12]], zeroinitializer ; TF-SCALABLE-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call @llvm.masked.gather.nxv2i64.nxv2p0( [[BROADCAST_SPLAT]], i32 8, [[TMP13]], poison) -; TF-SCALABLE-NEXT: [[TMP14:%.*]] = xor [[TMP12]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer) -; TF-SCALABLE-NEXT: [[TMP15:%.*]] = select [[ACTIVE_LANE_MASK]], [[TMP14]], zeroinitializer -; TF-SCALABLE-NEXT: [[TMP17:%.*]] = or [[TMP13]], [[TMP15]] ; TF-SCALABLE-NEXT: [[PREDPHI:%.*]] = select [[TMP13]], [[WIDE_MASKED_GATHER]], zeroinitializer ; TF-SCALABLE-NEXT: [[TMP16:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[TMP11]] ; TF-SCALABLE-NEXT: [[TMP18:%.*]] = getelementptr inbounds i64, ptr [[TMP16]], i32 0 -; TF-SCALABLE-NEXT: call void @llvm.masked.store.nxv2i64.p0( [[PREDPHI]], ptr [[TMP18]], i32 8, [[TMP17]]) +; TF-SCALABLE-NEXT: call void @llvm.masked.store.nxv2i64.p0( [[PREDPHI]], ptr [[TMP18]], i32 8, [[ACTIVE_LANE_MASK]]) ; TF-SCALABLE-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], [[TMP20]] ; TF-SCALABLE-NEXT: [[VEC_IND_NEXT]] = add [[VEC_IND]], [[DOTSPLAT]] ; TF-SCALABLE-NEXT: [[TMP21:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] @@ -510,13 +507,10 @@ define void @conditional_uniform_load(ptr noalias nocapture %a, ptr noalias noca ; TF-FIXEDLEN-NEXT: [[TMP1:%.*]] = icmp ugt <4 x i64> [[VEC_IND]], ; TF-FIXEDLEN-NEXT: [[TMP2:%.*]] = select <4 x i1> [[ACTIVE_LANE_MASK]], <4 x i1> [[TMP1]], <4 x i1> zeroinitializer ; TF-FIXEDLEN-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call <4 x i64> @llvm.masked.gather.v4i64.v4p0(<4 x ptr> [[BROADCAST_SPLAT]], i32 8, <4 x i1> [[TMP2]], <4 x i64> poison) -; TF-FIXEDLEN-NEXT: [[TMP3:%.*]] = xor <4 x i1> [[TMP1]], -; TF-FIXEDLEN-NEXT: [[TMP4:%.*]] = select <4 x i1> [[ACTIVE_LANE_MASK]], <4 x i1> [[TMP3]], <4 x i1> zeroinitializer -; TF-FIXEDLEN-NEXT: [[TMP6:%.*]] = or <4 x i1> [[TMP2]], [[TMP4]] ; TF-FIXEDLEN-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[TMP2]], <4 x i64> [[WIDE_MASKED_GATHER]], <4 x i64> zeroinitializer ; TF-FIXEDLEN-NEXT: [[TMP5:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[TMP0]] ; TF-FIXEDLEN-NEXT: [[TMP7:%.*]] = getelementptr inbounds i64, ptr [[TMP5]], i32 0 -; TF-FIXEDLEN-NEXT: call void @llvm.masked.store.v4i64.p0(<4 x i64> [[PREDPHI]], ptr [[TMP7]], i32 8, <4 x i1> [[TMP6]]) +; TF-FIXEDLEN-NEXT: call void @llvm.masked.store.v4i64.p0(<4 x i64> [[PREDPHI]], ptr [[TMP7]], i32 8, <4 x i1> [[ACTIVE_LANE_MASK]]) ; TF-FIXEDLEN-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 ; TF-FIXEDLEN-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], ; TF-FIXEDLEN-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1028 @@ -1296,12 +1290,9 @@ define void @conditional_uniform_store(ptr noalias nocapture %a, ptr noalias noc ; TF-SCALABLE-NEXT: [[TMP12:%.*]] = icmp ugt [[VEC_IND]], shufflevector ( insertelement ( poison, i64 10, i64 0), poison, zeroinitializer) ; TF-SCALABLE-NEXT: [[TMP13:%.*]] = select [[ACTIVE_LANE_MASK]], [[TMP12]], zeroinitializer ; TF-SCALABLE-NEXT: call void @llvm.masked.scatter.nxv2i64.nxv2p0( [[BROADCAST_SPLAT]], [[BROADCAST_SPLAT2]], i32 8, [[TMP13]]) -; TF-SCALABLE-NEXT: [[TMP15:%.*]] = xor [[TMP12]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer) -; TF-SCALABLE-NEXT: [[TMP16:%.*]] = select [[ACTIVE_LANE_MASK]], [[TMP15]], zeroinitializer -; TF-SCALABLE-NEXT: [[TMP17:%.*]] = or [[TMP13]], [[TMP16]] ; TF-SCALABLE-NEXT: [[TMP14:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[TMP11]] ; TF-SCALABLE-NEXT: [[TMP18:%.*]] = getelementptr inbounds i64, ptr [[TMP14]], i32 0 -; TF-SCALABLE-NEXT: call void @llvm.masked.store.nxv2i64.p0( [[BROADCAST_SPLAT]], ptr [[TMP18]], i32 8, [[TMP17]]) +; TF-SCALABLE-NEXT: call void @llvm.masked.store.nxv2i64.p0( [[BROADCAST_SPLAT]], ptr [[TMP18]], i32 8, [[ACTIVE_LANE_MASK]]) ; TF-SCALABLE-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], [[TMP20]] ; TF-SCALABLE-NEXT: [[VEC_IND_NEXT]] = add [[VEC_IND]], [[DOTSPLAT]] ; TF-SCALABLE-NEXT: [[TMP21:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] @@ -1344,12 +1335,9 @@ define void @conditional_uniform_store(ptr noalias nocapture %a, ptr noalias noc ; TF-FIXEDLEN-NEXT: [[TMP1:%.*]] = icmp ugt <4 x i64> [[VEC_IND]], ; TF-FIXEDLEN-NEXT: [[TMP2:%.*]] = select <4 x i1> [[ACTIVE_LANE_MASK]], <4 x i1> [[TMP1]], <4 x i1> zeroinitializer ; TF-FIXEDLEN-NEXT: call void @llvm.masked.scatter.v4i64.v4p0(<4 x i64> [[BROADCAST_SPLAT]], <4 x ptr> [[BROADCAST_SPLAT2]], i32 8, <4 x i1> [[TMP2]]) -; TF-FIXEDLEN-NEXT: [[TMP4:%.*]] = xor <4 x i1> [[TMP1]], -; TF-FIXEDLEN-NEXT: [[TMP5:%.*]] = select <4 x i1> [[ACTIVE_LANE_MASK]], <4 x i1> [[TMP4]], <4 x i1> zeroinitializer -; TF-FIXEDLEN-NEXT: [[TMP6:%.*]] = or <4 x i1> [[TMP2]], [[TMP5]] ; TF-FIXEDLEN-NEXT: [[TMP3:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[TMP0]] ; TF-FIXEDLEN-NEXT: [[TMP7:%.*]] = getelementptr inbounds i64, ptr [[TMP3]], i32 0 -; TF-FIXEDLEN-NEXT: call void @llvm.masked.store.v4i64.p0(<4 x i64> [[BROADCAST_SPLAT]], ptr [[TMP7]], i32 8, <4 x i1> [[TMP6]]) +; TF-FIXEDLEN-NEXT: call void @llvm.masked.store.v4i64.p0(<4 x i64> [[BROADCAST_SPLAT]], ptr [[TMP7]], i32 8, <4 x i1> [[ACTIVE_LANE_MASK]]) ; TF-FIXEDLEN-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 ; TF-FIXEDLEN-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], ; TF-FIXEDLEN-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1028 diff --git a/llvm/test/Transforms/LoopVectorize/uniform-blend.ll b/llvm/test/Transforms/LoopVectorize/uniform-blend.ll index 19cbcac6090c..f33ec1419b11 100644 --- a/llvm/test/Transforms/LoopVectorize/uniform-blend.ll +++ b/llvm/test/Transforms/LoopVectorize/uniform-blend.ll @@ -86,11 +86,8 @@ define void @blend_chain_iv(i1 %c) { ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ] ; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i64> [ , %vector.ph ], [ [[VEC_IND_NEXT:%.*]], %vector.body ] ; CHECK-NEXT: [[TMP6:%.*]] = select <4 x i1> [[MASK1]], <4 x i1> [[MASK1]], <4 x i1> zeroinitializer -; CHECK-NEXT: [[TMP4:%.*]] = xor <4 x i1> [[MASK1]], -; CHECK-NEXT: [[TMP5:%.*]] = select <4 x i1> [[MASK1]], <4 x i1> [[TMP4]], <4 x i1> zeroinitializer -; CHECK-NEXT: [[TMP8:%.*]] = or <4 x i1> [[TMP6]], [[TMP5]] ; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[TMP6]], <4 x i64> [[VEC_IND]], <4 x i64> undef -; CHECK-NEXT: [[PREDPHI1:%.*]] = select <4 x i1> [[TMP8]], <4 x i64> [[PREDPHI]], <4 x i64> undef +; CHECK-NEXT: [[PREDPHI1:%.*]] = select <4 x i1> [[MASK1]], <4 x i64> [[PREDPHI]], <4 x i64> undef ; CHECK-NEXT: [[TMP9:%.*]] = extractelement <4 x i64> [[PREDPHI1]], i32 0 ; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds [32 x i16], ptr @dst, i16 0, i64 [[TMP9]] ; CHECK-NEXT: [[TMP11:%.*]] = extractelement <4 x i64> [[PREDPHI1]], i32 1 diff --git a/llvm/test/Transforms/LoopVectorize/unused-blend-mask-for-first-operand.ll b/llvm/test/Transforms/LoopVectorize/unused-blend-mask-for-first-operand.ll index 0f7bd3d71feb..d79b4a7cefc2 100644 --- a/llvm/test/Transforms/LoopVectorize/unused-blend-mask-for-first-operand.ll +++ b/llvm/test/Transforms/LoopVectorize/unused-blend-mask-for-first-operand.ll @@ -172,8 +172,6 @@ define void @test_not_first_lane_only_wide_compare_incoming_order_swapped(ptr %A ; CHECK: vector.ph: ; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i16> poison, i16 [[X]], i64 0 ; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT]], <4 x i16> poison, <4 x i32> zeroinitializer -; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <4 x i16> poison, i16 [[Y]], i64 0 -; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT1]], <4 x i16> poison, <4 x i32> zeroinitializer ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] @@ -184,14 +182,8 @@ define void @test_not_first_lane_only_wide_compare_incoming_order_swapped(ptr %A ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i16>, ptr [[TMP2]], align 2 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ult <4 x i16> [[WIDE_LOAD]], [[BROADCAST_SPLAT]] ; CHECK-NEXT: [[TMP4:%.*]] = xor <4 x i1> [[TMP3]], -; CHECK-NEXT: [[TMP5:%.*]] = icmp ult <4 x i16> [[WIDE_LOAD]], [[BROADCAST_SPLAT2]] -; CHECK-NEXT: [[TMP6:%.*]] = select <4 x i1> [[TMP4]], <4 x i1> [[TMP5]], <4 x i1> zeroinitializer -; CHECK-NEXT: [[TMP7:%.*]] = xor <4 x i1> [[TMP5]], -; CHECK-NEXT: [[TMP8:%.*]] = select <4 x i1> [[TMP4]], <4 x i1> [[TMP7]], <4 x i1> zeroinitializer -; CHECK-NEXT: [[TMP9:%.*]] = extractelement <4 x i1> [[TMP6]], i32 0 -; CHECK-NEXT: [[TMP10:%.*]] = extractelement <4 x i1> [[TMP8]], i32 0 -; CHECK-NEXT: [[TMP11:%.*]] = or i1 [[TMP9]], [[TMP10]] -; CHECK-NEXT: [[PREDPHI:%.*]] = select i1 [[TMP11]], ptr [[B]], ptr poison +; CHECK-NEXT: [[TMP9:%.*]] = extractelement <4 x i1> [[TMP4]], i32 0 +; CHECK-NEXT: [[PREDPHI:%.*]] = select i1 [[TMP9]], ptr [[B]], ptr poison ; CHECK-NEXT: [[TMP12:%.*]] = load i16, ptr [[PREDPHI]], align 2 ; CHECK-NEXT: [[BROADCAST_SPLATINSERT3:%.*]] = insertelement <4 x i16> poison, i16 [[TMP12]], i64 0 ; CHECK-NEXT: [[BROADCAST_SPLAT4:%.*]] = shufflevector <4 x i16> [[BROADCAST_SPLATINSERT3]], <4 x i16> poison, <4 x i32> zeroinitializer diff --git a/llvm/test/Transforms/LoopVectorize/vplan-sink-scalars-and-merge.ll b/llvm/test/Transforms/LoopVectorize/vplan-sink-scalars-and-merge.ll index 1e60e57a5409..ae5879bb2bae 100644 --- a/llvm/test/Transforms/LoopVectorize/vplan-sink-scalars-and-merge.ll +++ b/llvm/test/Transforms/LoopVectorize/vplan-sink-scalars-and-merge.ll @@ -361,15 +361,12 @@ define void @pred_cfg1(i32 %k, i32 %j) { ; CHECK-NEXT: Successor(s): then.0.0 ; CHECK-EMPTY: ; CHECK-NEXT: then.0.0: -; CHECK-NEXT: EMIT vp<[[NOT:%.+]]> = not ir<%c.1> -; CHECK-NEXT: EMIT vp<[[MASK3:%.+]]> = logical-and vp<[[MASK1]]>, vp<[[NOT]]> -; CHECK-NEXT: EMIT vp<[[OR:%.+]]> = or vp<[[MASK2]]>, vp<[[MASK3]]> ; CHECK-NEXT: BLEND ir<%p> = ir<0> vp<[[PRED]]>/vp<[[MASK2]]> ; CHECK-NEXT: Successor(s): pred.store ; CHECK-EMPTY: ; CHECK-NEXT: pred.store: { ; CHECK-NEXT: pred.store.entry: -; CHECK-NEXT: BRANCH-ON-MASK vp<[[OR]]> +; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK1]]> ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue ; CHECK-EMPTY: ; CHECK-NEXT: pred.store.if: @@ -462,16 +459,13 @@ define void @pred_cfg2(i32 %k, i32 %j) { ; CHECK-NEXT: Successor(s): then.0.0 ; CHECK-EMPTY: ; CHECK-NEXT: then.0.0: -; CHECK-NEXT: EMIT vp<[[NOT:%.+]]> = not ir<%c.0> -; CHECK-NEXT: EMIT vp<[[MASK3:%.+]]> = logical-and vp<[[MASK1]]>, vp<[[NOT]]> -; CHECK-NEXT: EMIT vp<[[OR:%.+]]> = or vp<[[MASK2]]>, vp<[[MASK3]]> ; CHECK-NEXT: BLEND ir<%p> = ir<0> vp<[[PRED]]>/vp<[[MASK2]]> -; CHECK-NEXT: EMIT vp<[[MASK4:%.+]]> = logical-and vp<[[OR]]>, ir<%c.1> +; CHECK-NEXT: EMIT vp<[[MASK3:%.+]]> = logical-and vp<[[MASK1]]>, ir<%c.1> ; CHECK-NEXT: Successor(s): pred.store ; CHECK-EMPTY: ; CHECK-NEXT: pred.store: { ; CHECK-NEXT: pred.store.entry: -; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK4]]> +; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK3]]> ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue ; CHECK-EMPTY: ; CHECK-NEXT: pred.store.if: @@ -570,16 +564,13 @@ define void @pred_cfg3(i32 %k, i32 %j) { ; CHECK-NEXT: Successor(s): then.0.0 ; CHECK-EMPTY: ; CHECK-NEXT: then.0.0: -; CHECK-NEXT: EMIT vp<[[NOT:%.+]]> = not ir<%c.0> -; CHECK-NEXT: EMIT vp<[[MASK3:%.+]]> = logical-and vp<[[MASK1]]>, vp<[[NOT]]> -; CHECK-NEXT: EMIT vp<[[MASK4:%.+]]> = or vp<[[MASK2]]>, vp<[[MASK3]]> ; CHECK-NEXT: BLEND ir<%p> = ir<0> vp<[[PRED]]>/vp<[[MASK2]]> -; CHECK-NEXT: EMIT vp<[[MASK5:%.+]]> = logical-and vp<[[MASK4]]>, ir<%c.0> +; CHECK-NEXT: EMIT vp<[[MASK3:%.+]]> = logical-and vp<[[MASK1]]>, ir<%c.0> ; CHECK-NEXT: Successor(s): pred.store ; CHECK-EMPTY: ; CHECK-NEXT: pred.store: { ; CHECK-NEXT: pred.store.entry: -; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK5]]> +; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK3]]> ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue ; CHECK-EMPTY: ; CHECK-NEXT: pred.store.if: -- GitLab From 643f36184bd3d9a95cbfd608af6f1cccc69e0187 Mon Sep 17 00:00:00 2001 From: Helena Kotas Date: Sun, 19 May 2024 09:27:56 -0700 Subject: [PATCH 031/793] HLSL availability diagnostics design doc (#92207) Design document for the HLSL availability diagnostic modes Fixes microsoft/hlsl-specs#190 --------- Co-authored-by: Xiang Li --- clang/docs/HLSL/AvailabilityDiagnostics.rst | 137 ++++++++++++++++++++ clang/docs/HLSL/HLSLDocs.rst | 1 + 2 files changed, 138 insertions(+) create mode 100644 clang/docs/HLSL/AvailabilityDiagnostics.rst diff --git a/clang/docs/HLSL/AvailabilityDiagnostics.rst b/clang/docs/HLSL/AvailabilityDiagnostics.rst new file mode 100644 index 000000000000..bb9d02f21dde --- /dev/null +++ b/clang/docs/HLSL/AvailabilityDiagnostics.rst @@ -0,0 +1,137 @@ +============================= +HLSL Availability Diagnostics +============================= + +.. contents:: + :local: + +Introduction +============ + +HLSL availability diagnostics emits errors or warning when unavailable shader APIs are used. Unavailable shader APIs are APIs that are exposed in HLSL code but are not available in the target shader stage or shader model version. + +There are three modes of HLSL availability diagnostic: + +#. **Default mode** - compiler emits an error when an unavailable API is found in a code that is reachable from the shader entry point function or from an exported library function (when compiling a shader library) + +#. **Relaxed mode** - same as default mode except the compiler emits a warning. This mode is enabled by ``-Wno-error=hlsl-availability``. + +#. **Strict mode** - compiler emits an error when an unavailable API is found in parsed code regardless of whether it can be reached from the shader entry point or exported functions, or not. This mode is enabled by ``-fhlsl-strict-availability``. + +Implementation Details +====================== + +Environment Parameter +--------------------- + +In order to encode API availability based on the shader model version and shader model stage a new ``environment`` parameter was added to the existing Clang ``availability`` attribute. + +The values allowed for this parameter are a subset of values allowed as the ``llvm::Triple`` environment component. If the environment parameters is present, the declared availability attribute applies only to targets with the same platform and environment. + +Default and Relaxed Diagnostic Modes +------------------------------------ + +This mode is implemented in ``DiagnoseHLSLAvailability`` class in ``SemaHLSL.cpp`` and it is invoked after the whole translation unit is parsed (from ``Sema::ActOnEndOfTranslationUnit``). The implementation iterates over all shader entry points and exported library functions in the translation unit and performs an AST traversal of each function body. + +When a reference to another function or member method is found (``DeclRefExpr`` or ``MemberExpr``) and it has a body, the AST of the referenced function is also scanned. This chain of AST traversals will reach all of the code that is reachable from the initial shader entry point or exported library function and avoids the need to generate a call graph. + +All shader APIs have an availability attribute that specifies the shader model version (and environment, if applicable) when this API was first introduced.When a reference to a function without a definition is found and it has an availability attribute, the version of the attribute is checked against the target shader model version and shader stage (if shader stage context is known), and an appropriate diagnostic is generated as needed. + +All shader entry functions have ``HLSLShaderAttr`` attribute that specifies what type of shader this function represents. However, for exported library functions the target shader stage is unknown, so in this case the HLSL API availability will be only checked against the shader model version. It means that for exported library functions the diagnostic of APIs with availability specific to shader stage will be deferred until DXIL linking time. + +A list of functions that were already scanned is kept in order to avoid duplicate scans and diagnostics (see ``DiagnoseHLSLAvailability::ScannedDecls``). It might happen that a shader library has multiple shader entry points for different shader stages that all call into the same shared function. It is therefore important to record not just that a function has been scanned, but also in which shader stage context. This is done by using ``llvm::DenseMap`` that maps ``FunctionDecl *`` to a ``unsigned`` bitmap that represents a set of shader stages (or environments) the function has been scanned for. The ``N``'th bit in the set is set if the function has been scanned in shader environment whose ``HLSLShaderAttr::ShaderType`` integer value equals ``N``. + +The emitted diagnostic messages belong to ``hlsl-availability`` diagnostic group and are reported as errors by default. With ``-Wno-error=hlsl-availability`` flag they become warning, making it relaxed HLSL diagnostics mode. + +Strict Diagnostic Mode +---------------------- + +When strict HLSL availability diagnostic mode is enabled the compiler must report all HLSL API availability issues regardless of code reachability. The implementation of this mode takes advantage of an existing diagnostic scan in ``DiagnoseUnguardedAvailability`` class which is already traversing AST of each function as soon as the function body has been parsed. For HLSL, this pass was only slightly modified, such as making sure diagnostic messages are in the ``hlsl-availability`` group and that availability checks based on shader stage are not included if the shader stage context is unknown. + +If the compilation target is a shader library, only availability based on shader model version can be diagnosed during this scan. To diagnose availability based on shader stage, the compiler needs to run the AST traversals implementated in ``DiagnoseHLSLAvailability`` at the end of the translation unit as described above. + +As a result, availability based on specific shader stage will only be diagnosed in code that is reachable from a shader entry point or library export function. It also means that function bodies might be scanned multiple time. When that happens, care should be taken not to produce duplicated diagnostics. + +======== +Examples +======== + +**Note** +For the example below, the ``WaveActiveCountBits`` API function became available in shader model 6.0 and ``WaveMultiPrefixSum`` in shader model 6.5. + +The availability of ``ddx`` function depends on a shader stage. It is available for pixel shaders in shader model 2.1 and higher, for compute, mesh and amplification shaders in shader model 6.6 and higher. For any other shader stages it is not available. + +Compute shader example +====================== + +.. code-block:: c++ + + float unusedFunction(float f) { + return ddx(f); + } + + [numthreads(4, 4, 1)] + void main(uint3 threadId : SV_DispatchThreadId) { + float f1 = ddx(threadId.x); + float f2 = WaveActiveCountBits(threadId.y == 1.0); + } + +When compiled as compute shader for shader model version 5.0, Clang will emit the following error by default: + +.. code-block:: console + + <>:7:13: error: 'ddx' is only available in compute shader environment on Shader Model 6.6 or newer + <>:8:13: error: 'WaveActiveCountBits' is only available on Shader Model 6.5 or newer + +With relaxed diagnostic mode this errors will become warnings. + +With strict diagnostic mode, in addition to the 2 errors above Clang will also emit error for the ``ddx`` call in ``unusedFunction``.: + +.. code-block:: console + + <>:2:9: error: 'ddx' is only available in compute shader environment on Shader Model 6.5 or newer + <>:7:13: error: 'ddx' is only available in compute shader environment on Shader Model 6.5 or newer + <>:7:13: error: 'WaveActiveCountBits' is only available on Shader Model 6.5 or newer + +Shader library example +====================== + +.. code-block:: c++ + + float myFunction(float f) { + return ddx(f); + } + + float unusedFunction(float f) { + return WaveMultiPrefixSum(f, 1.0); + } + + [shader("compute")] + [numthreads(4, 4, 1)] + void main(uint3 threadId : SV_DispatchThreadId) { + float f = 3; + float e = myFunction(f); + } + + [shader("pixel")] + void main() { + float f = 3; + float e = myFunction(f); + } + +When compiled as shader library vshader model version 6.4, Clang will emit the following error by default: + +.. code-block:: console + + <>:2:9: error: 'ddx' is only available in compute shader environment on Shader Model 6.5 or newer + +With relaxed diagnostic mode this errors will become warnings. + +With strict diagnostic mode Clang will also emit errors for availability issues in code that is not used by any of the entry points: + +.. code-block:: console + + <>2:9: error: 'ddx' is only available in compute shader environment on Shader Model 6.6 or newer + <>:6:9: error: 'WaveActiveCountBits' is only available on Shader Model 6.5 or newer + +Note that ``myFunction`` is reachable from both pixel and compute shader entry points is therefore scanned twice - once for each context. The diagnostic is emitted only for the compute shader context. diff --git a/clang/docs/HLSL/HLSLDocs.rst b/clang/docs/HLSL/HLSLDocs.rst index 97b2425f013b..1e50a66d984b 100644 --- a/clang/docs/HLSL/HLSLDocs.rst +++ b/clang/docs/HLSL/HLSLDocs.rst @@ -16,3 +16,4 @@ HLSL Design and Implementation ResourceTypes EntryFunctions FunctionCalls + AvailabilityDiagnostics -- GitLab From c34079c9455515fd1eb4feaa7613a57e88b7209d Mon Sep 17 00:00:00 2001 From: Isaac David <61389980+orion160@users.noreply.github.com> Date: Sun, 19 May 2024 11:39:46 -0500 Subject: [PATCH 032/793] [DOCS] ORCv2.rst Typo (#89482) --- llvm/docs/ORCv2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/docs/ORCv2.rst b/llvm/docs/ORCv2.rst index 910ef5b9f3d0..333977a0aaa6 100644 --- a/llvm/docs/ORCv2.rst +++ b/llvm/docs/ORCv2.rst @@ -780,7 +780,7 @@ constructs a new ThreadSafeContext value from a std::unique_ptr: // separate context. for (const auto &IRPath : IRPaths) { auto Ctx = std::make_unique(); - auto M = std::make_unique("M", *Ctx); + auto M = std::make_unique("M", *Ctx); CompileLayer.add(MainJD, ThreadSafeModule(std::move(M), std::move(Ctx))); } -- GitLab From 3f33c4c14e79e68007cf1460e4a0e606eb199da5 Mon Sep 17 00:00:00 2001 From: Helena Kotas Date: Sun, 19 May 2024 10:46:12 -0700 Subject: [PATCH 033/793] [Clang][HLSL] Add environment parameter to availability attribute (#89809) Add `environment` parameter to Clang availability attribute. The allowed values for this parameter are a subset of values allowed in the `llvm::Triple` environment component. If the `environment` parameters is present, the declared availability attribute applies only to targets with the same platform and environment. This new parameter will be initially used for annotating HLSL functions for the `shadermodel` platform because in HLSL built-in function availability can depend not just on the shader model version (mapped to `llvm::Triple::OSType`) but also on the target shader stage (mapped to `llvm::Triple::EnvironmentType`). See example in #89802 and microsoft/hlsl-specs#204 for more details. The environment parameter is currently supported only for HLSL. Fixes #89802 --- clang/include/clang/Basic/Attr.td | 33 ++++- clang/include/clang/Basic/AttrDocs.td | 5 + .../clang/Basic/DiagnosticParseKinds.td | 2 + .../clang/Basic/DiagnosticSemaKinds.td | 17 ++- clang/include/clang/Parse/Parser.h | 3 + clang/include/clang/Sema/ParsedAttr.h | 42 ++++-- clang/include/clang/Sema/Sema.h | 15 +- clang/lib/AST/DeclBase.cpp | 28 +++- clang/lib/Headers/hlsl/hlsl_intrinsics.h | 15 +- clang/lib/Index/CommentToXML.cpp | 6 + clang/lib/Parse/ParseDecl.cpp | 20 ++- clang/lib/Sema/SemaAPINotes.cpp | 3 +- clang/lib/Sema/SemaAvailability.cpp | 128 +++++++++++++----- clang/lib/Sema/SemaDecl.cpp | 2 +- clang/lib/Sema/SemaDeclAttr.cpp | 48 +++++-- clang/test/Parser/attr-availability.c | 2 + clang/test/Sema/attr-availability-ios.c | 1 + .../attr-availability-compute.hlsl | 73 ++++++++++ .../attr-availability-errors.hlsl | 11 ++ .../Availability/attr-availability-mesh.hlsl | 73 ++++++++++ .../Availability/attr-availability-pixel.hlsl | 63 +++++++++ clang/test/SemaHLSL/AvailabilityMarkup.hlsl | 25 ---- .../SemaHLSL/WaveBuiltinAvailability.hlsl | 4 +- 23 files changed, 508 insertions(+), 111 deletions(-) create mode 100644 clang/test/SemaHLSL/Availability/attr-availability-compute.hlsl create mode 100644 clang/test/SemaHLSL/Availability/attr-availability-errors.hlsl create mode 100644 clang/test/SemaHLSL/Availability/attr-availability-mesh.hlsl create mode 100644 clang/test/SemaHLSL/Availability/attr-availability-pixel.hlsl delete mode 100644 clang/test/SemaHLSL/AvailabilityMarkup.hlsl diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 38ee8356583b..7008bea483c8 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -999,7 +999,7 @@ def Availability : InheritableAttr { VersionArgument<"deprecated">, VersionArgument<"obsoleted">, BoolArgument<"unavailable">, StringArgument<"message">, BoolArgument<"strict">, StringArgument<"replacement">, - IntArgument<"priority">]; + IntArgument<"priority">, IdentifierArgument<"environment">]; let AdditionalMembers = [{static llvm::StringRef getPrettyPlatformName(llvm::StringRef Platform) { return llvm::StringSwitch(Platform) @@ -1019,7 +1019,7 @@ def Availability : InheritableAttr { .Case("xros", "visionOS") .Case("xros_app_extension", "visionOS (App Extension)") .Case("swift", "Swift") - .Case("shadermodel", "HLSL ShaderModel") + .Case("shadermodel", "Shader Model") .Case("ohos", "OpenHarmony OS") .Default(llvm::StringRef()); } @@ -1059,7 +1059,34 @@ static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) { .Case("visionos_app_extension", "xros_app_extension") .Case("ShaderModel", "shadermodel") .Default(Platform); -} }]; +} +static llvm::StringRef getPrettyEnviromentName(llvm::StringRef Environment) { + return llvm::StringSwitch(Environment) + .Case("pixel", "pixel shader") + .Case("vertex", "vertex shader") + .Case("geometry", "geometry shader") + .Case("hull", "hull shader") + .Case("domain", "domain shader") + .Case("compute", "compute shader") + .Case("mesh", "mesh shader") + .Case("amplification", "amplification shader") + .Case("library", "shader library") + .Default(Environment); +} +static llvm::Triple::EnvironmentType getEnvironmentType(llvm::StringRef Environment) { + return llvm::StringSwitch(Environment) + .Case("pixel", llvm::Triple::Pixel) + .Case("vertex", llvm::Triple::Vertex) + .Case("geometry", llvm::Triple::Geometry) + .Case("hull", llvm::Triple::Hull) + .Case("domain", llvm::Triple::Domain) + .Case("compute", llvm::Triple::Compute) + .Case("mesh", llvm::Triple::Mesh) + .Case("amplification", llvm::Triple::Amplification) + .Case("library", llvm::Triple::Library) + .Default(llvm::Triple::UnknownEnvironment); +} +}]; let HasCustomParsing = 1; let InheritEvenIfAlreadyPresent = 1; let Subjects = SubjectList<[Named]>; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index b48aaf65558a..54197d588eb4 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -1593,6 +1593,11 @@ replacement=\ *string-literal* a warning about use of a deprecated declaration. The Fix-It will replace the deprecated declaration with the new declaration specified. +environment=\ *identifier* + Target environment in which this declaration is available. If present, + the availability attribute applies only to targets with the same platform + and environment. The parameter is currently supported only in HLSL. + Multiple availability attributes can be placed on a declaration, which may correspond to different platforms. For most platforms, the availability attribute with the platform corresponding to the target platform will be used; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 8316845844cb..46656fc66044 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1112,6 +1112,8 @@ def err_zero_version : Error< "version number must have non-zero major, minor, or sub-minor version">; def err_availability_expected_platform : Error< "expected a platform name, e.g., 'macos'">; +def err_availability_expected_environment : Error< + "expected an environment name, e.g., 'compute'">; // objc_bridge_related attribute def err_objcbridge_related_expected_related_class : Error< diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 09b1874f9fdd..e3b4186f1b06 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3837,6 +3837,9 @@ def note_cannot_use_trivial_abi_reason : Note< // Availability attribute def warn_availability_unknown_platform : Warning< "unknown platform %0 in availability macro">, InGroup; +def warn_availability_unknown_environment : Warning< + "unknown environment %0 in availability macro">, InGroup; + def warn_availability_version_ordering : Warning< "feature cannot be %select{introduced|deprecated|obsoleted}0 in %1 version " "%2 before it was %select{introduced|deprecated|obsoleted}3 in version %4; " @@ -3867,13 +3870,21 @@ def note_protocol_method : Note< def warn_availability_fuchsia_unavailable_minor : Warning< "Fuchsia API Level prohibits specifying a minor or sub-minor version">, InGroup; +def err_availability_unexpected_parameter: Error< + "unexpected parameter '%0' in availability attribute, not permitted in %select{HLSL|C/C++}1">; def warn_unguarded_availability : - Warning<"%0 is only available on %1 %2 or newer">, + Warning<"%0 is only available %select{|in %4 environment }3on %1 %2 or newer">, + InGroup, DefaultIgnore; +def warn_unguarded_availability_unavailable : + Warning<"%0 is unavailable">, InGroup, DefaultIgnore; def warn_unguarded_availability_new : Warning, InGroup; +def warn_unguarded_availability_unavailable_new : + Warning, + InGroup; def note_decl_unguarded_availability_silence : Note< "annotate %select{%1|anonymous %1}0 with an availability attribute to silence this warning">; def note_unguarded_available_silence : Note< @@ -5870,8 +5881,8 @@ def note_availability_specified_here : Note< "%0 has been explicitly marked " "%select{unavailable|deleted|deprecated}1 here">; def note_partial_availability_specified_here : Note< - "%0 has been marked as being introduced in %1 %2 here, " - "but the deployment target is %1 %3">; + "%0 has been marked as being introduced in %1 %2 %select{|in %5 environment }4here, " + "but the deployment target is %1 %3%select{| %6 environment }4">; def note_implicitly_deleted : Note< "explicitly defaulted function was implicitly deleted here">; def warn_not_enough_argument : Warning< diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 1e796e828b10..5f04664141d2 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -153,6 +153,9 @@ class Parser : public CodeCompletionHandler { /// Identifier for "replacement". IdentifierInfo *Ident_replacement; + /// Identifier for "environment". + IdentifierInfo *Ident_environment; + /// Identifiers used by the 'external_source_symbol' attribute. IdentifierInfo *Ident_language, *Ident_defined_in, *Ident_generated_declaration, *Ident_USR; diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h index 8368d9ce6146..22cbd0d90ee4 100644 --- a/clang/include/clang/Sema/ParsedAttr.h +++ b/clang/include/clang/Sema/ParsedAttr.h @@ -40,6 +40,7 @@ class LangOptions; class Sema; class Stmt; class TargetInfo; +struct IdentifierLoc; /// Represents information about a change in availability for /// an entity, which is part of the encoding of the 'availability' @@ -68,12 +69,14 @@ struct AvailabilityData { AvailabilityChange Changes[NumAvailabilitySlots]; SourceLocation StrictLoc; const Expr *Replacement; + const IdentifierLoc *EnvironmentLoc; AvailabilityData(const AvailabilityChange &Introduced, const AvailabilityChange &Deprecated, - const AvailabilityChange &Obsoleted, - SourceLocation Strict, const Expr *ReplaceExpr) - : StrictLoc(Strict), Replacement(ReplaceExpr) { + const AvailabilityChange &Obsoleted, SourceLocation Strict, + const Expr *ReplaceExpr, const IdentifierLoc *EnvironmentLoc) + : StrictLoc(Strict), Replacement(ReplaceExpr), + EnvironmentLoc(EnvironmentLoc) { Changes[IntroducedSlot] = Introduced; Changes[DeprecatedSlot] = Deprecated; Changes[ObsoletedSlot] = Obsoleted; @@ -234,7 +237,7 @@ private: const AvailabilityChange &deprecated, const AvailabilityChange &obsoleted, SourceLocation unavailable, const Expr *messageExpr, Form formUsed, SourceLocation strict, - const Expr *replacementExpr) + const Expr *replacementExpr, const IdentifierLoc *environmentLoc) : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed), NumArgs(1), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), @@ -243,8 +246,9 @@ private: Info(ParsedAttrInfo::get(*this)) { ArgsUnion PVal(Parm); memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); - new (getAvailabilityData()) detail::AvailabilityData( - introduced, deprecated, obsoleted, strict, replacementExpr); + new (getAvailabilityData()) + detail::AvailabilityData(introduced, deprecated, obsoleted, strict, + replacementExpr, environmentLoc); } /// Constructor for objc_bridge_related attributes. @@ -445,6 +449,12 @@ public: return getAvailabilityData()->Replacement; } + const IdentifierLoc *getEnvironment() const { + assert(getParsedKind() == AT_Availability && + "Not an availability attribute"); + return getAvailabilityData()->EnvironmentLoc; + } + const ParsedType &getMatchingCType() const { assert(getParsedKind() == AT_TypeTagForDatatype && "Not a type_tag_for_datatype attribute"); @@ -759,11 +769,13 @@ public: const AvailabilityChange &obsoleted, SourceLocation unavailable, const Expr *MessageExpr, ParsedAttr::Form form, SourceLocation strict, - const Expr *ReplacementExpr) { + const Expr *ReplacementExpr, + IdentifierLoc *EnvironmentLoc) { void *memory = allocate(AttributeFactory::AvailabilityAllocSize); - return add(new (memory) ParsedAttr( - attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, - obsoleted, unavailable, MessageExpr, form, strict, ReplacementExpr)); + return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, + Param, introduced, deprecated, obsoleted, + unavailable, MessageExpr, form, strict, + ReplacementExpr, EnvironmentLoc)); } ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, @@ -994,10 +1006,12 @@ public: const AvailabilityChange &obsoleted, SourceLocation unavailable, const Expr *MessageExpr, ParsedAttr::Form form, SourceLocation strict, - const Expr *ReplacementExpr) { - ParsedAttr *attr = pool.create( - attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, - obsoleted, unavailable, MessageExpr, form, strict, ReplacementExpr); + const Expr *ReplacementExpr, + IdentifierLoc *EnvironmentLoc) { + ParsedAttr *attr = + pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced, + deprecated, obsoleted, unavailable, MessageExpr, form, + strict, ReplacementExpr, EnvironmentLoc); addAtEnd(attr); return attr; } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index b16a304960d3..6c89d275215d 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -39,6 +39,7 @@ #include "clang/Basic/Cuda.h" #include "clang/Basic/DarwinSDKInfo.h" #include "clang/Basic/ExpressionTraits.h" +#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/Module.h" #include "clang/Basic/OpenCLOptions.h" #include "clang/Basic/PragmaKinds.h" @@ -3580,13 +3581,13 @@ public: bool CheckAttrTarget(const ParsedAttr &CurrAttr); bool CheckAttrNoArgs(const ParsedAttr &CurrAttr); - AvailabilityAttr * - mergeAvailabilityAttr(NamedDecl *D, const AttributeCommonInfo &CI, - IdentifierInfo *Platform, bool Implicit, - VersionTuple Introduced, VersionTuple Deprecated, - VersionTuple Obsoleted, bool IsUnavailable, - StringRef Message, bool IsStrict, StringRef Replacement, - AvailabilityMergeKind AMK, int Priority); + AvailabilityAttr *mergeAvailabilityAttr( + NamedDecl *D, const AttributeCommonInfo &CI, IdentifierInfo *Platform, + bool Implicit, VersionTuple Introduced, VersionTuple Deprecated, + VersionTuple Obsoleted, bool IsUnavailable, StringRef Message, + bool IsStrict, StringRef Replacement, AvailabilityMergeKind AMK, + int Priority, IdentifierInfo *IIEnvironment); + TypeVisibilityAttr * mergeTypeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI, TypeVisibilityAttr::VisibilityType Vis); diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 03e1055251c2..65d5eeb6354e 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -666,12 +666,28 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, // Make sure that this declaration has already been introduced. if (!A->getIntroduced().empty() && EnclosingVersion < A->getIntroduced()) { - if (Message) { - Message->clear(); - llvm::raw_string_ostream Out(*Message); - VersionTuple VTI(A->getIntroduced()); - Out << "introduced in " << PrettyPlatformName << ' ' - << VTI << HintMessage; + IdentifierInfo *IIEnv = A->getEnvironment(); + StringRef TargetEnv = + Context.getTargetInfo().getTriple().getEnvironmentName(); + StringRef EnvName = AvailabilityAttr::getPrettyEnviromentName(TargetEnv); + // Matching environment or no environment on attribute + if (!IIEnv || (!TargetEnv.empty() && IIEnv->getName() == TargetEnv)) { + if (Message) { + Message->clear(); + llvm::raw_string_ostream Out(*Message); + VersionTuple VTI(A->getIntroduced()); + Out << "introduced in " << PrettyPlatformName << " " << VTI << " " + << EnvName << HintMessage; + } + } + // Non-matching environment or no environment on target + else { + if (Message) { + Message->clear(); + llvm::raw_string_ostream Out(*Message); + Out << "not available on " << PrettyPlatformName << " " << EnvName + << HintMessage; + } } return A->getStrict() ? AR_Unavailable : AR_NotYetIntroduced; diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 3390f0962f67..bc72e8a00e0d 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -18,14 +18,21 @@ namespace hlsl { #define _HLSL_BUILTIN_ALIAS(builtin) \ __attribute__((clang_builtin_alias(builtin))) -#define _HLSL_AVAILABILITY(environment, version) \ - __attribute__((availability(environment, introduced = version))) +#define _HLSL_AVAILABILITY(platform, version) \ + __attribute__((availability(platform, introduced = version))) +#define _HLSL_AVAILABILITY_STAGE(platform, version, stage) \ + __attribute__(( \ + availability(platform, introduced = version, environment = stage))) #ifdef __HLSL_ENABLE_16_BIT -#define _HLSL_16BIT_AVAILABILITY(environment, version) \ - __attribute__((availability(environment, introduced = version))) +#define _HLSL_16BIT_AVAILABILITY(platform, version) \ + __attribute__((availability(platform, introduced = version))) +#define _HLSL_16BIT_AVAILABILITY_STAGE(platform, version, stage) \ + __attribute__(( \ + availability(platform, introduced = version, environment = stage))) #else #define _HLSL_16BIT_AVAILABILITY(environment, version) +#define _HLSL_16BIT_AVAILABILITY_STAGE(environment, version, stage) #endif //===----------------------------------------------------------------------===// diff --git a/clang/lib/Index/CommentToXML.cpp b/clang/lib/Index/CommentToXML.cpp index 295f3f228ff7..3372fbba4383 100644 --- a/clang/lib/Index/CommentToXML.cpp +++ b/clang/lib/Index/CommentToXML.cpp @@ -12,6 +12,7 @@ #include "clang/AST/Comment.h" #include "clang/AST/CommentVisitor.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceManager.h" #include "clang/Format/Format.h" #include "clang/Index/USRGeneration.h" @@ -1052,6 +1053,11 @@ void CommentASTToXMLConverter::visitFullComment(const FullComment *C) { } if (AA->getUnavailable()) Result << ""; + + IdentifierInfo *Environment = AA->getEnvironment(); + if (Environment) { + Result << "" << Environment->getName() << ""; + } Result << ""; } } diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 2ce8fa98089f..445d3fd66e38 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1256,6 +1256,7 @@ void Parser::ParseAvailabilityAttribute( enum { Introduced, Deprecated, Obsoleted, Unknown }; AvailabilityChange Changes[Unknown]; ExprResult MessageExpr, ReplacementExpr; + IdentifierLoc *EnvironmentLoc = nullptr; // Opening '('. BalancedDelimiterTracker T(*this, tok::l_paren); @@ -1303,6 +1304,7 @@ void Parser::ParseAvailabilityAttribute( Ident_message = PP.getIdentifierInfo("message"); Ident_strict = PP.getIdentifierInfo("strict"); Ident_replacement = PP.getIdentifierInfo("replacement"); + Ident_environment = PP.getIdentifierInfo("environment"); } // Parse the optional "strict", the optional "replacement" and the set of @@ -1350,6 +1352,13 @@ void Parser::ParseAvailabilityAttribute( continue; } + if (Keyword == Ident_environment) { + if (EnvironmentLoc != nullptr) { + Diag(KeywordLoc, diag::err_availability_redundant) + << Keyword << SourceRange(EnvironmentLoc->Loc); + } + } + if (Tok.isNot(tok::equal)) { Diag(Tok, diag::err_expected_after) << Keyword << tok::equal; SkipUntil(tok::r_paren, StopAtSemi); @@ -1371,6 +1380,15 @@ void Parser::ParseAvailabilityAttribute( continue; } } + if (Keyword == Ident_environment) { + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_availability_expected_environment); + SkipUntil(tok::r_paren, StopAtSemi); + return; + } + EnvironmentLoc = ParseIdentifierLoc(); + continue; + } // Special handling of 'NA' only when applied to introduced or // deprecated. @@ -1452,7 +1470,7 @@ void Parser::ParseAvailabilityAttribute( SourceRange(AvailabilityLoc, T.getCloseLocation()), ScopeName, ScopeLoc, Platform, Changes[Introduced], Changes[Deprecated], Changes[Obsoleted], UnavailableLoc, MessageExpr.get(), Form, - StrictLoc, ReplacementExpr.get()); + StrictLoc, ReplacementExpr.get(), EnvironmentLoc); } /// Parse the contents of the "external_source_symbol" attribute. diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index 443bf162044f..c80b08e361cf 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -269,7 +269,8 @@ static void ProcessAPINotes(Sema &S, Decl *D, ASTAllocateString(S.Context, Info.UnavailableMsg), /*Strict=*/false, /*Replacement=*/StringRef(), - /*Priority=*/Sema::AP_Explicit); + /*Priority=*/Sema::AP_Explicit, + /*Environment=*/nullptr); }, [](const Decl *D) { return llvm::find_if(D->attrs(), [](const Attr *next) -> bool { diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp index 5ebc25317bf3..663b6f35b869 100644 --- a/clang/lib/Sema/SemaAvailability.cpp +++ b/clang/lib/Sema/SemaAvailability.cpp @@ -14,20 +14,37 @@ #include "clang/AST/Decl.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaObjC.h" +#include "llvm/ADT/StringRef.h" #include using namespace clang; using namespace sema; +static bool hasMatchingEnvironmentOrNone(const ASTContext &Context, + const AvailabilityAttr *AA) { + IdentifierInfo *IIEnvironment = AA->getEnvironment(); + auto Environment = Context.getTargetInfo().getTriple().getEnvironment(); + if (!IIEnvironment || Environment == llvm::Triple::UnknownEnvironment) + return true; + + llvm::Triple::EnvironmentType ET = + AvailabilityAttr::getEnvironmentType(IIEnvironment->getName()); + return Environment == ET; +} + static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context, const Decl *D) { + AvailabilityAttr const *PartialMatch = nullptr; // Check each AvailabilityAttr to find the one for this platform. + // For multiple attributes with the same platform try to find one for this + // environment. for (const auto *A : D->attrs()) { if (const auto *Avail = dyn_cast(A)) { // FIXME: this is copied from CheckAvailability. We should try to @@ -46,11 +63,15 @@ static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context, StringRef TargetPlatform = Context.getTargetInfo().getPlatformName(); // Match the platform name. - if (RealizedPlatform == TargetPlatform) - return Avail; + if (RealizedPlatform == TargetPlatform) { + // Find the best matching attribute for this environment + if (hasMatchingEnvironmentOrNone(Context, Avail)) + return Avail; + PartialMatch = Avail; + } } } - return nullptr; + return PartialMatch; } /// The diagnostic we should emit for \c D, and the declaration that @@ -118,10 +139,9 @@ ShouldDiagnoseAvailabilityOfDecl(Sema &S, const NamedDecl *D, /// whether we should emit a diagnostic for \c K and \c DeclVersion in /// the context of \c Ctx. For example, we should emit an unavailable diagnostic /// in a deprecated context, but not the other way around. -static bool -ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K, - VersionTuple DeclVersion, Decl *Ctx, - const NamedDecl *OffendingDecl) { +static bool ShouldDiagnoseAvailabilityInContext( + Sema &S, AvailabilityResult K, VersionTuple DeclVersion, + const IdentifierInfo *DeclEnv, Decl *Ctx, const NamedDecl *OffendingDecl) { assert(K != AR_Available && "Expected an unavailable declaration here!"); // If this was defined using CF_OPTIONS, etc. then ignore the diagnostic. @@ -140,7 +160,8 @@ ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K, auto CheckContext = [&](const Decl *C) { if (K == AR_NotYetIntroduced) { if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, C)) - if (AA->getIntroduced() >= DeclVersion) + if (AA->getIntroduced() >= DeclVersion && + AA->getEnvironment() == DeclEnv) return true; } else if (K == AR_Deprecated) { if (C->isDeprecated()) @@ -344,10 +365,14 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, unsigned available_here_select_kind; VersionTuple DeclVersion; - if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, OffendingDecl)) + const AvailabilityAttr *AA = getAttrForPlatform(S.Context, OffendingDecl); + const IdentifierInfo *IIEnv = nullptr; + if (AA) { DeclVersion = AA->getIntroduced(); + IIEnv = AA->getEnvironment(); + } - if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, Ctx, + if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, IIEnv, Ctx, OffendingDecl)) return; @@ -355,8 +380,7 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, // The declaration can have multiple availability attributes, we are looking // at one of them. - const AvailabilityAttr *A = getAttrForPlatform(S.Context, OffendingDecl); - if (A && A->isInherited()) { + if (AA && AA->isInherited()) { for (const Decl *Redecl = OffendingDecl->getMostRecentDecl(); Redecl; Redecl = Redecl->getPreviousDecl()) { const AvailabilityAttr *AForRedecl = @@ -376,26 +400,43 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, // not specified for deployment targets >= to iOS 11 or equivalent or // for declarations that were introduced in iOS 11 (macOS 10.13, ...) or // later. - const AvailabilityAttr *AA = - getAttrForPlatform(S.getASTContext(), OffendingDecl); + assert(AA != nullptr && "expecting valid availability attribute"); VersionTuple Introduced = AA->getIntroduced(); + bool EnvironmentMatchesOrNone = + hasMatchingEnvironmentOrNone(S.getASTContext(), AA); + + const TargetInfo &TI = S.getASTContext().getTargetInfo(); + std::string PlatformName( + AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName())); + llvm::StringRef TargetEnvironment(AvailabilityAttr::getPrettyEnviromentName( + TI.getTriple().getEnvironmentName())); + llvm::StringRef AttrEnvironment = + AA->getEnvironment() ? AvailabilityAttr::getPrettyEnviromentName( + AA->getEnvironment()->getName()) + : ""; + bool UseEnvironment = + (!AttrEnvironment.empty() && !TargetEnvironment.empty()); bool UseNewWarning = shouldDiagnoseAvailabilityByDefault( S.Context, S.Context.getTargetInfo().getPlatformMinVersion(), Introduced); - unsigned Warning = UseNewWarning ? diag::warn_unguarded_availability_new - : diag::warn_unguarded_availability; - std::string PlatformName(AvailabilityAttr::getPrettyPlatformName( - S.getASTContext().getTargetInfo().getPlatformName())); + unsigned DiagKind = + EnvironmentMatchesOrNone + ? (UseNewWarning ? diag::warn_unguarded_availability_new + : diag::warn_unguarded_availability) + : (UseNewWarning ? diag::warn_unguarded_availability_unavailable_new + : diag::warn_unguarded_availability_unavailable); - S.Diag(Loc, Warning) << OffendingDecl << PlatformName - << Introduced.getAsString(); + S.Diag(Loc, DiagKind) << OffendingDecl << PlatformName + << Introduced.getAsString() << UseEnvironment + << TargetEnvironment; S.Diag(OffendingDecl->getLocation(), diag::note_partial_availability_specified_here) << OffendingDecl << PlatformName << Introduced.getAsString() - << S.Context.getTargetInfo().getPlatformMinVersion().getAsString(); + << S.Context.getTargetInfo().getPlatformMinVersion().getAsString() + << UseEnvironment << AttrEnvironment << TargetEnvironment; if (const auto *Enclosing = findEnclosingDeclToAnnotate(Ctx)) { if (const auto *TD = dyn_cast(Enclosing)) @@ -772,14 +813,17 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( const AvailabilityAttr *AA = getAttrForPlatform(SemaRef.getASTContext(), OffendingDecl); + bool EnvironmentMatchesOrNone = + hasMatchingEnvironmentOrNone(SemaRef.getASTContext(), AA); VersionTuple Introduced = AA->getIntroduced(); - if (AvailabilityStack.back() >= Introduced) + if (EnvironmentMatchesOrNone && AvailabilityStack.back() >= Introduced) return; // If the context of this function is less available than D, we should not // emit a diagnostic. - if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced, Ctx, + if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced, + AA->getEnvironment(), Ctx, OffendingDecl)) return; @@ -787,25 +831,39 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( // not specified for deployment targets >= to iOS 11 or equivalent or // for declarations that were introduced in iOS 11 (macOS 10.13, ...) or // later. - unsigned DiagKind = - shouldDiagnoseAvailabilityByDefault( - SemaRef.Context, - SemaRef.Context.getTargetInfo().getPlatformMinVersion(), Introduced) - ? diag::warn_unguarded_availability_new - : diag::warn_unguarded_availability; + bool UseNewDiagKind = shouldDiagnoseAvailabilityByDefault( + SemaRef.Context, + SemaRef.Context.getTargetInfo().getPlatformMinVersion(), Introduced); + + const TargetInfo &TI = SemaRef.getASTContext().getTargetInfo(); + std::string PlatformName( + AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName())); + llvm::StringRef TargetEnvironment(AvailabilityAttr::getPrettyEnviromentName( + TI.getTriple().getEnvironmentName())); + llvm::StringRef AttrEnvironment = + AA->getEnvironment() ? AvailabilityAttr::getPrettyEnviromentName( + AA->getEnvironment()->getName()) + : ""; + bool UseEnvironment = + (!AttrEnvironment.empty() && !TargetEnvironment.empty()); - std::string PlatformName(AvailabilityAttr::getPrettyPlatformName( - SemaRef.getASTContext().getTargetInfo().getPlatformName())); + unsigned DiagKind = + EnvironmentMatchesOrNone + ? (UseNewDiagKind ? diag::warn_unguarded_availability_new + : diag::warn_unguarded_availability) + : (UseNewDiagKind + ? diag::warn_unguarded_availability_unavailable_new + : diag::warn_unguarded_availability_unavailable); SemaRef.Diag(Range.getBegin(), DiagKind) - << Range << D << PlatformName << Introduced.getAsString(); + << Range << D << PlatformName << Introduced.getAsString() + << UseEnvironment << TargetEnvironment; SemaRef.Diag(OffendingDecl->getLocation(), diag::note_partial_availability_specified_here) << OffendingDecl << PlatformName << Introduced.getAsString() - << SemaRef.Context.getTargetInfo() - .getPlatformMinVersion() - .getAsString(); + << SemaRef.Context.getTargetInfo().getPlatformMinVersion().getAsString() + << UseEnvironment << AttrEnvironment << TargetEnvironment; auto FixitDiag = SemaRef.Diag(Range.getBegin(), diag::note_unguarded_available_silence) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f2b9202255cd..557fe10619c3 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2879,7 +2879,7 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, D, *AA, AA->getPlatform(), AA->isImplicit(), AA->getIntroduced(), AA->getDeprecated(), AA->getObsoleted(), AA->getUnavailable(), AA->getMessage(), AA->getStrict(), AA->getReplacement(), AMK, - AA->getPriority()); + AA->getPriority(), AA->getEnvironment()); else if (const auto *VA = dyn_cast(Attr)) NewAttr = S.mergeVisibilityAttr(D, *VA, VA->getVisibility()); else if (const auto *VA = dyn_cast(Attr)) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 30776ff537fb..ca5938083917 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -26,6 +26,7 @@ #include "clang/Basic/Cuda.h" #include "clang/Basic/DarwinSDKInfo.h" #include "clang/Basic/HLSLRuntime.h" +#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" @@ -52,6 +53,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/Triple.h" #include using namespace clang; @@ -2495,7 +2497,7 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr( bool Implicit, VersionTuple Introduced, VersionTuple Deprecated, VersionTuple Obsoleted, bool IsUnavailable, StringRef Message, bool IsStrict, StringRef Replacement, AvailabilityMergeKind AMK, - int Priority) { + int Priority, IdentifierInfo *Environment) { VersionTuple MergedIntroduced = Introduced; VersionTuple MergedDeprecated = Deprecated; VersionTuple MergedObsoleted = Obsoleted; @@ -2529,6 +2531,12 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr( continue; } + IdentifierInfo *OldEnvironment = OldAA->getEnvironment(); + if (OldEnvironment != Environment) { + ++i; + continue; + } + // If there is an existing availability attribute for this platform that // has a lower priority use the existing one and discard the new // attribute. @@ -2647,7 +2655,7 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr( !OverrideOrImpl) { auto *Avail = ::new (Context) AvailabilityAttr( Context, CI, Platform, Introduced, Deprecated, Obsoleted, IsUnavailable, - Message, IsStrict, Replacement, Priority); + Message, IsStrict, Replacement, Priority, Environment); Avail->setImplicit(Implicit); return Avail; } @@ -2706,13 +2714,34 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } } + if (S.getLangOpts().HLSL && IsStrict) + S.Diag(AL.getStrictLoc(), diag::err_availability_unexpected_parameter) + << "strict" << /* HLSL */ 0; + int PriorityModifier = AL.isPragmaClangAttribute() ? Sema::AP_PragmaClangAttribute : Sema::AP_Explicit; + + const IdentifierLoc *EnvironmentLoc = AL.getEnvironment(); + IdentifierInfo *IIEnvironment = nullptr; + if (EnvironmentLoc) { + if (S.getLangOpts().HLSL) { + IIEnvironment = EnvironmentLoc->Ident; + if (AvailabilityAttr::getEnvironmentType( + EnvironmentLoc->Ident->getName()) == + llvm::Triple::EnvironmentType::UnknownEnvironment) + S.Diag(EnvironmentLoc->Loc, diag::warn_availability_unknown_environment) + << EnvironmentLoc->Ident; + } else { + S.Diag(EnvironmentLoc->Loc, diag::err_availability_unexpected_parameter) + << "environment" << /* C/C++ */ 1; + } + } + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( ND, AL, II, false /*Implicit*/, Introduced.Version, Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, IsStrict, Replacement, - Sema::AMK_None, PriorityModifier); + Sema::AMK_None, PriorityModifier, IIEnvironment); if (NewAttr) D->addAttr(NewAttr); @@ -2768,8 +2797,8 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated, NewObsoleted, IsUnavailable, Str, IsStrict, Replacement, - Sema::AMK_None, - PriorityModifier + Sema::AP_InferredFromOtherPlatform); + Sema::AMK_None, PriorityModifier + Sema::AP_InferredFromOtherPlatform, + IIEnvironment); if (NewAttr) D->addAttr(NewAttr); } @@ -2810,8 +2839,8 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated, NewObsoleted, IsUnavailable, Str, IsStrict, Replacement, - Sema::AMK_None, - PriorityModifier + Sema::AP_InferredFromOtherPlatform); + Sema::AMK_None, PriorityModifier + Sema::AP_InferredFromOtherPlatform, + IIEnvironment); if (NewAttr) D->addAttr(NewAttr); } @@ -2844,7 +2873,7 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { MinMacCatalystVersion(Deprecated.Version), MinMacCatalystVersion(Obsoleted.Version), IsUnavailable, Str, IsStrict, Replacement, Sema::AMK_None, - PriorityModifier + Sema::AP_InferredFromOtherPlatform); + PriorityModifier + Sema::AP_InferredFromOtherPlatform, IIEnvironment); if (NewAttr) D->addAttr(NewAttr); } else if (II->getName() == "macos" && GetSDKInfo() && @@ -2887,7 +2916,8 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { VersionOrEmptyVersion(NewObsoleted), /*IsUnavailable=*/false, Str, IsStrict, Replacement, Sema::AMK_None, PriorityModifier + Sema::AP_InferredFromOtherPlatform + - Sema::AP_InferredFromOtherPlatform); + Sema::AP_InferredFromOtherPlatform, + IIEnvironment); if (NewAttr) D->addAttr(NewAttr); } diff --git a/clang/test/Parser/attr-availability.c b/clang/test/Parser/attr-availability.c index aab0f2f3a852..9d84d9c1df36 100644 --- a/clang/test/Parser/attr-availability.c +++ b/clang/test/Parser/attr-availability.c @@ -30,6 +30,8 @@ void f11(void) __attribute__((availability(macosx,message=u"b"))); // expected-w void f12(void) __attribute__((availability(macosx,message="a" u"b"))); // expected-warning {{encoding prefix 'u' on an unevaluated string literal has no effect}} +void f13(void) __attribute__((availability(shadermodel, introduced = 6.0, environment=pixel))); // expected-error {{unexpected parameter 'environment' in availability attribute, not permitted in C/C++}} + enum E{ gorf __attribute__((availability(macosx,introduced=8.5, message = 10.0))), // expected-error {{expected string literal for optional message in 'availability' attribute}} garf __attribute__((availability(macosx,introduced=8.5, message))), // expected-error {{expected '=' after 'message'}} diff --git a/clang/test/Sema/attr-availability-ios.c b/clang/test/Sema/attr-availability-ios.c index b97b7e688cc6..b001e70b5ff5 100644 --- a/clang/test/Sema/attr-availability-ios.c +++ b/clang/test/Sema/attr-availability-ios.c @@ -9,6 +9,7 @@ void f4(int) __attribute__((availability(macosx,introduced=10.1,deprecated=10.3, void f5(int) __attribute__((availability(ios,introduced=2.0))) __attribute__((availability(ios,deprecated=3.0))); // expected-note {{'f5' has been explicitly marked deprecated here}} void f6(int) __attribute__((availability(ios,deprecated=3.0))); // expected-note {{'f6' has been explicitly marked deprecated here}} void f6(int) __attribute__((availability(iOS,introduced=2.0))); +void f7(int) __attribute__((availability(ios,introduced=2.0, environment=e))); // expected-error {{unexpected parameter 'environment' in availability attribute, not permitted in C/C++}} void test(void) { f0(0); // expected-warning{{'f0' is deprecated: first deprecated in iOS 2.1}} diff --git a/clang/test/SemaHLSL/Availability/attr-availability-compute.hlsl b/clang/test/SemaHLSL/Availability/attr-availability-compute.hlsl new file mode 100644 index 000000000000..8fa696ea1164 --- /dev/null +++ b/clang/test/SemaHLSL/Availability/attr-availability-compute.hlsl @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel5.0-compute -fsyntax-only -verify %s + +// Platform shader model, no environment parameter +__attribute__((availability(shadermodel, introduced = 6.0))) +unsigned f1(); // #f1 + +__attribute__((availability(shadermodel, introduced = 5.1))) +unsigned f2(); // #f2 + +__attribute__((availability(shadermodel, introduced = 5.0))) +unsigned f3(); + +// Platform shader model, environment parameter restricting earlier version, +// available in all environments in higher versions +__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.0))) +unsigned f4(); // #f4 + +__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 5.0))) +unsigned f5(); + +// Platform shader model, environment parameter restricting earlier version, +// never available in all environments in higher versions +__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.0, environment = compute))) +__attribute__((availability(shadermodel, introduced = 5.0, environment = mesh))) +unsigned f6(); // #f6 + +__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh))) +unsigned f7(); // #f7 + +__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 5.0, environment = compute))) +__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh))) +unsigned f8(); + +[numthreads(4,1,1)] +int main() { + // expected-warning@#f1_call {{'f1' is only available on Shader Model 6.0 or newer}} + // expected-note@#f1 {{'f1' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} + // expected-note@#f1_call {{enclose 'f1' in a __builtin_available check to silence this warning}} + unsigned A = f1(); // #f1_call + + // expected-warning@#f2_call {{'f2' is only available on Shader Model 5.1 or newer}} + // expected-note@#f2 {{'f2' has been marked as being introduced in Shader Model 5.1 here, but the deployment target is Shader Model 5.0}} + // expected-note@#f2_call {{enclose 'f2' in a __builtin_available check to silence this warning}} + unsigned B = f2(); // #f2_call + + unsigned C = f3(); + + // expected-warning@#f4_call {{'f4' is only available on Shader Model 6.0 or newer}} + // expected-note@#f4 {{'f4' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} + // expected-note@#f4_call {{enclose 'f4' in a __builtin_available check to silence this warning}} + unsigned D = f4(); // #f4_call + + unsigned E = f5(); + + // expected-warning@#f6_call {{'f6' is only available in compute shader environment on Shader Model 6.0 or newer}} + // expected-note@#f6 {{'f6' has been marked as being introduced in Shader Model 6.0 in compute shader environment here, but the deployment target is Shader Model 5.0}} + // expected-note@#f6_call {{enclose 'f6' in a __builtin_available check to silence this warning}} + unsigned F = f6(); // #f6_call + + // expected-warning@#f7_call {{'f7' is unavailable}} + // expected-note@#f7 {{'f7' has been marked as being introduced in Shader Model 6.0 in mesh shader environment here, but the deployment target is Shader Model 5.0 compute shader environment}} + // expected-note@#f7_call {{enclose 'f7' in a __builtin_available check to silence this warning}} + unsigned G = f7(); // #f7_call + + unsigned H = f8(); + + return 0; +} diff --git a/clang/test/SemaHLSL/Availability/attr-availability-errors.hlsl b/clang/test/SemaHLSL/Availability/attr-availability-errors.hlsl new file mode 100644 index 000000000000..2682eb5fbb5c --- /dev/null +++ b/clang/test/SemaHLSL/Availability/attr-availability-errors.hlsl @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.5-library -fsyntax-only -verify %s + + +void f1(void) __attribute__((availability(shadermodel, introduced = 6.0, environment="pixel"))); // expected-error {{expected an environment name, e.g., 'compute'}} + +void f2(void) __attribute__((availability(shadermodel, introduced = 6.0, environment=pixel, environment=compute))); // expected-error {{redundant 'environment' availability change; only the last specified change will be used}} + +void f3(void) __attribute__((availability(shadermodel, strict, introduced = 6.0, environment = mesh))); // expected-error {{unexpected parameter 'strict' in availability attribute, not permitted in HLSL}} + +int main() { +} diff --git a/clang/test/SemaHLSL/Availability/attr-availability-mesh.hlsl b/clang/test/SemaHLSL/Availability/attr-availability-mesh.hlsl new file mode 100644 index 000000000000..40a7ddbb1de9 --- /dev/null +++ b/clang/test/SemaHLSL/Availability/attr-availability-mesh.hlsl @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel5.0-mesh -fsyntax-only -verify %s + +// Platform shader model, no environment parameter +__attribute__((availability(shadermodel, introduced = 6.0))) +unsigned f1(); // #f1 + +__attribute__((availability(shadermodel, introduced = 5.1))) +unsigned f2(); // #f2 + +__attribute__((availability(shadermodel, introduced = 5.0))) +unsigned f3(); + +// Platform shader model, environment parameter restricting earlier version, +// available in all environments in higher versions +__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.0))) +unsigned f4(); // #f4 + +__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 5.0))) +unsigned f5(); // #f5 + +// Platform shader model, environment parameter restricting earlier version, +// never available in all environments in higher versions +__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.0, environment = compute))) +__attribute__((availability(shadermodel, introduced = 5.0, environment = mesh))) +unsigned f6(); // #f6 + +__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh))) +unsigned f7(); // #f7 + +__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 5.0, environment = compute))) +__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh))) +unsigned f8(); // #f8 + +[numthreads(4,1,1)] +int main() { + // expected-warning@#f1_call {{'f1' is only available on Shader Model 6.0 or newer}} + // expected-note@#f1 {{'f1' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} + // expected-note@#f1_call {{enclose 'f1' in a __builtin_available check to silence this warning}} + unsigned A = f1(); // #f1_call + + // expected-warning@#f2_call {{'f2' is only available on Shader Model 5.1 or newer}} + // expected-note@#f2 {{'f2' has been marked as being introduced in Shader Model 5.1 here, but the deployment target is Shader Model 5.0}} + // expected-note@#f2_call {{enclose 'f2' in a __builtin_available check to silence this warning}} + unsigned B = f2(); // #f2_call + + unsigned C = f3(); + + // expected-warning@#f4_call {{'f4' is only available on Shader Model 6.0 or newer}} + // expected-note@#f4 {{'f4' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} + // expected-note@#f4_call {{enclose 'f4' in a __builtin_available check to silence this warning}} + unsigned D = f4(); // #f4_call + + unsigned E = f5(); // #f5_call + + unsigned F = f6(); // #f6_call + + // expected-warning@#f7_call {{'f7' is only available in mesh shader environment on Shader Model 6.0 or newer}} + // expected-note@#f7 {{'f7' has been marked as being introduced in Shader Model 6.0 in mesh shader environment here, but the deployment target is Shader Model 5.0 mesh shader environment}} + // expected-note@#f7_call {{enclose 'f7' in a __builtin_available check to silence this warning}} + unsigned G = f7(); // #f7_call + + // expected-warning@#f8_call {{'f8' is only available in mesh shader environment on Shader Model 6.0 or newer}} + // expected-note@#f8 {{'f8' has been marked as being introduced in Shader Model 6.0 in mesh shader environment here, but the deployment target is Shader Model 5.0 mesh shader environment}} + // expected-note@#f8_call {{enclose 'f8' in a __builtin_available check to silence this warning}} + unsigned H = f8(); // #f8_call + + return 0; +} diff --git a/clang/test/SemaHLSL/Availability/attr-availability-pixel.hlsl b/clang/test/SemaHLSL/Availability/attr-availability-pixel.hlsl new file mode 100644 index 000000000000..59d09a9cd276 --- /dev/null +++ b/clang/test/SemaHLSL/Availability/attr-availability-pixel.hlsl @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel5.0-pixel -fsyntax-only -verify %s + +// Platform shader model, no environment parameter +__attribute__((availability(shadermodel, introduced = 6.0))) +unsigned f1(); // #f1 + +__attribute__((availability(shadermodel, introduced = 5.1))) +unsigned f2(); // #f2 + +__attribute__((availability(shadermodel, introduced = 5.0))) +unsigned f3(); + +// Platform shader model, environment parameter restricting earlier version, +// available in all environments in higher versions +__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.0))) +unsigned f4(); // #f4 + +__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 5.0))) +unsigned f5(); + +// Platform shader model, environment parameter restricting earlier version, +// never available in all environments in higher versions +__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.0, environment = compute))) +__attribute__((availability(shadermodel, introduced = 5.0, environment = mesh))) +unsigned f6(); // #f6 + +__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh))) +unsigned f7(); // #f7 + +__attribute__((availability(shadermodel, introduced = 2.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 5.0, environment = compute))) +__attribute__((availability(shadermodel, introduced = 6.0, environment = mesh))) +unsigned f8(); + +int main() { + // expected-warning@#f1_call {{'f1' is only available on Shader Model 6.0 or newer}} + // expected-note@#f1 {{'f1' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} + // expected-note@#f1_call {{enclose 'f1' in a __builtin_available check to silence this warning}} + unsigned A = f1(); // #f1_call + + // expected-warning@#f2_call {{'f2' is only available on Shader Model 5.1 or newer}} + // expected-note@#f2 {{'f2' has been marked as being introduced in Shader Model 5.1 here, but the deployment target is Shader Model 5.0}} + // expected-note@#f2_call {{enclose 'f2' in a __builtin_available check to silence this warning}} + unsigned B = f2(); // #f2_call + + unsigned C = f3(); + + unsigned D = f4(); // #f4_call + + unsigned E = f5(); + + unsigned F = f6(); // #f6_call + + unsigned G = f7(); // #f7_call + + unsigned H = f8(); + + return 0; +} diff --git a/clang/test/SemaHLSL/AvailabilityMarkup.hlsl b/clang/test/SemaHLSL/AvailabilityMarkup.hlsl deleted file mode 100644 index b883957af087..000000000000 --- a/clang/test/SemaHLSL/AvailabilityMarkup.hlsl +++ /dev/null @@ -1,25 +0,0 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel5.0-library -verify %s - -__attribute__((availability(shadermodel, introduced = 6.0))) -unsigned fn6_0(); // #fn6_0 - -__attribute__((availability(shadermodel, introduced = 5.1))) -unsigned fn5_1(); // #fn5_1 - -__attribute__((availability(shadermodel, introduced = 5.0))) -unsigned fn5_0(); - -void fn() { - // expected-warning@#fn6_0_site {{'fn6_0' is only available on HLSL ShaderModel 6.0 or newer}} - // expected-note@#fn6_0 {{'fn6_0' has been marked as being introduced in HLSL ShaderModel 6.0 here, but the deployment target is HLSL ShaderModel 5.0}} - // expected-note@#fn6_0_site {{enclose 'fn6_0' in a __builtin_available check to silence this warning}} - unsigned A = fn6_0(); // #fn6_0_site - - // expected-warning@#fn5_1_site {{'fn5_1' is only available on HLSL ShaderModel 5.1 or newer}} - // expected-note@#fn5_1 {{'fn5_1' has been marked as being introduced in HLSL ShaderModel 5.1 here, but the deployment target is HLSL ShaderModel 5.0}} - // expected-note@#fn5_1_site {{enclose 'fn5_1' in a __builtin_available check to silence this warning}} - unsigned B = fn5_1(); // #fn5_1_site - - unsigned C = fn5_0(); -} - diff --git a/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl b/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl index 0e45edc6a4c8..185b79be37be 100644 --- a/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl +++ b/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl @@ -2,8 +2,8 @@ // WaveActiveCountBits is unavailable before ShaderModel 6.0. unsigned foo(bool b) { - // expected-warning@#site {{'WaveActiveCountBits' is only available on HLSL ShaderModel 6.0 or newer}} - // expected-note@hlsl/hlsl_intrinsics.h:* {{'WaveActiveCountBits' has been marked as being introduced in HLSL ShaderModel 6.0 here, but the deployment target is HLSL ShaderModel 5.0}} + // expected-warning@#site {{'WaveActiveCountBits' is only available on Shader Model 6.0 or newer}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{'WaveActiveCountBits' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} // expected-note@#site {{enclose 'WaveActiveCountBits' in a __builtin_available check to silence this warning}} return hlsl::WaveActiveCountBits(b); // #site } -- GitLab From 0cd2bf3521a52f255c2b0d466f2f48f15d4a89a9 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sun, 19 May 2024 20:56:21 +0200 Subject: [PATCH 034/793] ValueTracking: Correct undef handling for constant FP vectors (#92557) Treat undef as unknown, and poison as ignorable. --- llvm/lib/Analysis/ValueTracking.cpp | 2 +- .../AMDGPU/amdgpu-codegenprepare-fdiv.ll | 130 +++++++++--------- llvm/test/Transforms/Attributor/nofpclass.ll | 2 +- llvm/test/Transforms/InstCombine/and-fcmp.ll | 27 +++- llvm/test/Transforms/InstCombine/or-fcmp.ll | 49 ++++++- 5 files changed, 135 insertions(+), 75 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index e8c5f9b3dc25..2d1486d252c3 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4751,7 +4751,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, Known = KnownFPClass(); return; } - if (isa(Elt)) + if (isa(Elt)) continue; auto *CElt = dyn_cast(Elt); if (!CElt) { diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-fdiv.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-fdiv.ll index 6bda962d1b9c..b69afa3ab1f3 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-fdiv.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-fdiv.ll @@ -2151,7 +2151,7 @@ define amdgpu_kernel void @rsq_f32_vector_fpmath(ptr addrspace(1) %out, <2 x flo ; IEEE-GOODFREXP-NEXT: [[TMP29:%.*]] = extractvalue { float, i32 } [[TMP28]], 0 ; IEEE-GOODFREXP-NEXT: [[TMP30:%.*]] = extractvalue { float, i32 } [[TMP28]], 1 ; IEEE-GOODFREXP-NEXT: [[TMP31:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP29]]) -; IEEE-GOODFREXP-NEXT: [[TMP32:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float undef) +; IEEE-GOODFREXP-NEXT: [[TMP32:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float poison) ; IEEE-GOODFREXP-NEXT: [[TMP33:%.*]] = extractvalue { float, i32 } [[TMP32]], 0 ; IEEE-GOODFREXP-NEXT: [[TMP34:%.*]] = extractvalue { float, i32 } [[TMP32]], 1 ; IEEE-GOODFREXP-NEXT: [[TMP35:%.*]] = fmul contract float [[TMP33]], [[TMP31]] @@ -2222,9 +2222,9 @@ define amdgpu_kernel void @rsq_f32_vector_fpmath(ptr addrspace(1) %out, <2 x flo ; IEEE-BADFREXP-NEXT: [[TMP29:%.*]] = extractvalue { float, i32 } [[TMP28]], 0 ; IEEE-BADFREXP-NEXT: [[TMP30:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float [[TMP19]]) ; IEEE-BADFREXP-NEXT: [[TMP31:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP29]]) -; IEEE-BADFREXP-NEXT: [[TMP32:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float undef) +; IEEE-BADFREXP-NEXT: [[TMP32:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float poison) ; IEEE-BADFREXP-NEXT: [[TMP33:%.*]] = extractvalue { float, i32 } [[TMP32]], 0 -; IEEE-BADFREXP-NEXT: [[TMP34:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float undef) +; IEEE-BADFREXP-NEXT: [[TMP34:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float poison) ; IEEE-BADFREXP-NEXT: [[TMP35:%.*]] = fmul contract float [[TMP33]], [[TMP31]] ; IEEE-BADFREXP-NEXT: [[TMP36:%.*]] = sub i32 [[TMP34]], [[TMP30]] ; IEEE-BADFREXP-NEXT: [[TMP37:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP35]], i32 [[TMP36]]) @@ -2281,7 +2281,7 @@ define amdgpu_kernel void @rsq_f32_vector_fpmath(ptr addrspace(1) %out, <2 x flo ; DAZ-NEXT: [[TMP17:%.*]] = extractvalue { float, i32 } [[TMP16]], 0 ; DAZ-NEXT: [[TMP18:%.*]] = extractvalue { float, i32 } [[TMP16]], 1 ; DAZ-NEXT: [[TMP19:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP17]]) -; DAZ-NEXT: [[TMP20:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float undef) +; DAZ-NEXT: [[TMP20:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float poison) ; DAZ-NEXT: [[TMP21:%.*]] = extractvalue { float, i32 } [[TMP20]], 0 ; DAZ-NEXT: [[TMP22:%.*]] = extractvalue { float, i32 } [[TMP20]], 1 ; DAZ-NEXT: [[TMP23:%.*]] = fmul contract float [[TMP21]], [[TMP19]] @@ -2313,7 +2313,7 @@ define amdgpu_kernel void @rsq_f32_vector_fpmath(ptr addrspace(1) %out, <2 x flo ; Matches the rsq instruction accuracy %sqrt.md.1ulp.undef = call contract <2 x float> @llvm.sqrt.v2f32(<2 x float> %x), !fpmath !2 - %md.1ulp.undef = fdiv contract <2 x float> , %sqrt.md.1ulp.undef, !fpmath !2 + %md.1ulp.undef = fdiv contract <2 x float> , %sqrt.md.1ulp.undef, !fpmath !2 store volatile <2 x float> %md.1ulp.undef, ptr addrspace(1) %out, align 4 ; Test mismatched metadata/flags between the sqrt and fdiv @@ -3121,7 +3121,7 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator(<4 x float> %arg) { ; IEEE-GOODFREXP-NEXT: [[TMP32:%.*]] = extractvalue { float, i32 } [[TMP31]], 0 ; IEEE-GOODFREXP-NEXT: [[TMP33:%.*]] = extractvalue { float, i32 } [[TMP31]], 1 ; IEEE-GOODFREXP-NEXT: [[TMP34:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP32]]) -; IEEE-GOODFREXP-NEXT: [[TMP35:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float undef) +; IEEE-GOODFREXP-NEXT: [[TMP35:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float poison) ; IEEE-GOODFREXP-NEXT: [[TMP36:%.*]] = extractvalue { float, i32 } [[TMP35]], 0 ; IEEE-GOODFREXP-NEXT: [[TMP37:%.*]] = extractvalue { float, i32 } [[TMP35]], 1 ; IEEE-GOODFREXP-NEXT: [[TMP38:%.*]] = fmul contract float [[TMP36]], [[TMP34]] @@ -3170,9 +3170,9 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator(<4 x float> %arg) { ; IEEE-BADFREXP-NEXT: [[TMP32:%.*]] = extractvalue { float, i32 } [[TMP31]], 0 ; IEEE-BADFREXP-NEXT: [[TMP33:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float [[TMP4]]) ; IEEE-BADFREXP-NEXT: [[TMP34:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP32]]) -; IEEE-BADFREXP-NEXT: [[TMP35:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float undef) +; IEEE-BADFREXP-NEXT: [[TMP35:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float poison) ; IEEE-BADFREXP-NEXT: [[TMP36:%.*]] = extractvalue { float, i32 } [[TMP35]], 0 -; IEEE-BADFREXP-NEXT: [[TMP37:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float undef) +; IEEE-BADFREXP-NEXT: [[TMP37:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float poison) ; IEEE-BADFREXP-NEXT: [[TMP38:%.*]] = fmul contract float [[TMP36]], [[TMP34]] ; IEEE-BADFREXP-NEXT: [[TMP39:%.*]] = sub i32 [[TMP37]], [[TMP33]] ; IEEE-BADFREXP-NEXT: [[TMP40:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP38]], i32 [[TMP39]]) @@ -3217,7 +3217,7 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator(<4 x float> %arg) { ; DAZ-NEXT: [[TMP30:%.*]] = extractvalue { float, i32 } [[TMP29]], 0 ; DAZ-NEXT: [[TMP31:%.*]] = extractvalue { float, i32 } [[TMP29]], 1 ; DAZ-NEXT: [[TMP32:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP30]]) -; DAZ-NEXT: [[TMP33:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float undef) +; DAZ-NEXT: [[TMP33:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float poison) ; DAZ-NEXT: [[TMP34:%.*]] = extractvalue { float, i32 } [[TMP33]], 0 ; DAZ-NEXT: [[TMP35:%.*]] = extractvalue { float, i32 } [[TMP33]], 1 ; DAZ-NEXT: [[TMP36:%.*]] = fmul contract float [[TMP34]], [[TMP32]] @@ -3230,7 +3230,7 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator(<4 x float> %arg) { ; DAZ-NEXT: ret <4 x float> [[PARTIAL_RSQ]] ; %denom = call contract <4 x float> @llvm.sqrt.v4f32(<4 x float> %arg), !fpmath !2 - %partial.rsq = fdiv contract <4 x float> , %denom, !fpmath !2 + %partial.rsq = fdiv contract <4 x float> , %denom, !fpmath !2 ret <4 x float> %partial.rsq } @@ -3272,7 +3272,7 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_afn_sqrt(<4 x float> ; IEEE-GOODFREXP-NEXT: [[TMP32:%.*]] = extractvalue { float, i32 } [[TMP31]], 0 ; IEEE-GOODFREXP-NEXT: [[TMP33:%.*]] = extractvalue { float, i32 } [[TMP31]], 1 ; IEEE-GOODFREXP-NEXT: [[TMP34:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP32]]) -; IEEE-GOODFREXP-NEXT: [[TMP35:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float undef) +; IEEE-GOODFREXP-NEXT: [[TMP35:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float poison) ; IEEE-GOODFREXP-NEXT: [[TMP36:%.*]] = extractvalue { float, i32 } [[TMP35]], 0 ; IEEE-GOODFREXP-NEXT: [[TMP37:%.*]] = extractvalue { float, i32 } [[TMP35]], 1 ; IEEE-GOODFREXP-NEXT: [[TMP38:%.*]] = fmul contract float [[TMP36]], [[TMP34]] @@ -3321,9 +3321,9 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_afn_sqrt(<4 x float> ; IEEE-BADFREXP-NEXT: [[TMP32:%.*]] = extractvalue { float, i32 } [[TMP31]], 0 ; IEEE-BADFREXP-NEXT: [[TMP33:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float [[TMP4]]) ; IEEE-BADFREXP-NEXT: [[TMP34:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP32]]) -; IEEE-BADFREXP-NEXT: [[TMP35:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float undef) +; IEEE-BADFREXP-NEXT: [[TMP35:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float poison) ; IEEE-BADFREXP-NEXT: [[TMP36:%.*]] = extractvalue { float, i32 } [[TMP35]], 0 -; IEEE-BADFREXP-NEXT: [[TMP37:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float undef) +; IEEE-BADFREXP-NEXT: [[TMP37:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float poison) ; IEEE-BADFREXP-NEXT: [[TMP38:%.*]] = fmul contract float [[TMP36]], [[TMP34]] ; IEEE-BADFREXP-NEXT: [[TMP39:%.*]] = sub i32 [[TMP37]], [[TMP33]] ; IEEE-BADFREXP-NEXT: [[TMP40:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP38]], i32 [[TMP39]]) @@ -3361,7 +3361,7 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_afn_sqrt(<4 x float> ; DAZ-NEXT: [[TMP23:%.*]] = extractvalue { float, i32 } [[TMP22]], 0 ; DAZ-NEXT: [[TMP24:%.*]] = extractvalue { float, i32 } [[TMP22]], 1 ; DAZ-NEXT: [[TMP25:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP23]]) -; DAZ-NEXT: [[TMP26:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float undef) +; DAZ-NEXT: [[TMP26:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float poison) ; DAZ-NEXT: [[TMP27:%.*]] = extractvalue { float, i32 } [[TMP26]], 0 ; DAZ-NEXT: [[TMP28:%.*]] = extractvalue { float, i32 } [[TMP26]], 1 ; DAZ-NEXT: [[TMP29:%.*]] = fmul contract float [[TMP27]], [[TMP25]] @@ -3374,7 +3374,7 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_afn_sqrt(<4 x float> ; DAZ-NEXT: ret <4 x float> [[PARTIAL_RSQ]] ; %denom = call contract afn <4 x float> @llvm.sqrt.v4f32(<4 x float> %arg) - %partial.rsq = fdiv contract <4 x float> , %denom, !fpmath !2 + %partial.rsq = fdiv contract <4 x float> , %denom, !fpmath !2 ret <4 x float> %partial.rsq } @@ -3382,7 +3382,7 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_afn_div(<4 x float> ; IEEE-LABEL: define <4 x float> @rsq_f32_vector_mixed_constant_numerator_afn_div( ; IEEE-SAME: <4 x float> [[ARG:%.*]]) #[[ATTR1]] { ; IEEE-NEXT: [[DENOM:%.*]] = call contract <4 x float> @llvm.sqrt.v4f32(<4 x float> [[ARG]]), !fpmath [[META2:![0-9]+]] -; IEEE-NEXT: [[PARTIAL_RSQ:%.*]] = fdiv contract afn <4 x float> , [[DENOM]] +; IEEE-NEXT: [[PARTIAL_RSQ:%.*]] = fdiv contract afn <4 x float> , [[DENOM]] ; IEEE-NEXT: ret <4 x float> [[PARTIAL_RSQ]] ; ; DAZ-LABEL: define <4 x float> @rsq_f32_vector_mixed_constant_numerator_afn_div( @@ -3399,11 +3399,11 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_afn_div(<4 x float> ; DAZ-NEXT: [[TMP10:%.*]] = insertelement <4 x float> [[TMP9]], float [[TMP6]], i64 1 ; DAZ-NEXT: [[TMP11:%.*]] = insertelement <4 x float> [[TMP10]], float [[TMP7]], i64 2 ; DAZ-NEXT: [[DENOM:%.*]] = insertelement <4 x float> [[TMP11]], float [[TMP8]], i64 3 -; DAZ-NEXT: [[PARTIAL_RSQ:%.*]] = fdiv contract afn <4 x float> , [[DENOM]] +; DAZ-NEXT: [[PARTIAL_RSQ:%.*]] = fdiv contract afn <4 x float> , [[DENOM]] ; DAZ-NEXT: ret <4 x float> [[PARTIAL_RSQ]] ; %denom = call contract <4 x float> @llvm.sqrt.v4f32(<4 x float> %arg), !fpmath !2 - %partial.rsq = fdiv contract afn <4 x float> , %denom + %partial.rsq = fdiv contract afn <4 x float> , %denom ret <4 x float> %partial.rsq } @@ -3411,7 +3411,7 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_correct_fdiv(<4 x fl ; IEEE-LABEL: define <4 x float> @rsq_f32_vector_mixed_constant_numerator_correct_fdiv( ; IEEE-SAME: <4 x float> [[ARG:%.*]]) #[[ATTR1]] { ; IEEE-NEXT: [[DENOM:%.*]] = call contract <4 x float> @llvm.sqrt.v4f32(<4 x float> [[ARG]]), !fpmath [[META2]] -; IEEE-NEXT: [[PARTIAL_RSQ:%.*]] = fdiv contract <4 x float> , [[DENOM]] +; IEEE-NEXT: [[PARTIAL_RSQ:%.*]] = fdiv contract <4 x float> , [[DENOM]] ; IEEE-NEXT: ret <4 x float> [[PARTIAL_RSQ]] ; ; DAZ-LABEL: define <4 x float> @rsq_f32_vector_mixed_constant_numerator_correct_fdiv( @@ -3428,11 +3428,11 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_correct_fdiv(<4 x fl ; DAZ-NEXT: [[TMP10:%.*]] = insertelement <4 x float> [[TMP9]], float [[TMP6]], i64 1 ; DAZ-NEXT: [[TMP11:%.*]] = insertelement <4 x float> [[TMP10]], float [[TMP7]], i64 2 ; DAZ-NEXT: [[DENOM:%.*]] = insertelement <4 x float> [[TMP11]], float [[TMP8]], i64 3 -; DAZ-NEXT: [[PARTIAL_RSQ:%.*]] = fdiv contract <4 x float> , [[DENOM]] +; DAZ-NEXT: [[PARTIAL_RSQ:%.*]] = fdiv contract <4 x float> , [[DENOM]] ; DAZ-NEXT: ret <4 x float> [[PARTIAL_RSQ]] ; %denom = call contract <4 x float> @llvm.sqrt.v4f32(<4 x float> %arg), !fpmath !2 - %partial.rsq = fdiv contract <4 x float> , %denom + %partial.rsq = fdiv contract <4 x float> , %denom ret <4 x float> %partial.rsq } @@ -3471,7 +3471,7 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_correct_sqrt(<4 x fl ; IEEE-GOODFREXP-NEXT: [[TMP29:%.*]] = extractvalue { float, i32 } [[TMP28]], 0 ; IEEE-GOODFREXP-NEXT: [[TMP30:%.*]] = extractvalue { float, i32 } [[TMP28]], 1 ; IEEE-GOODFREXP-NEXT: [[TMP31:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP29]]) -; IEEE-GOODFREXP-NEXT: [[TMP32:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float undef) +; IEEE-GOODFREXP-NEXT: [[TMP32:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float poison) ; IEEE-GOODFREXP-NEXT: [[TMP33:%.*]] = extractvalue { float, i32 } [[TMP32]], 0 ; IEEE-GOODFREXP-NEXT: [[TMP34:%.*]] = extractvalue { float, i32 } [[TMP32]], 1 ; IEEE-GOODFREXP-NEXT: [[TMP35:%.*]] = fmul contract float [[TMP33]], [[TMP31]] @@ -3517,9 +3517,9 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_correct_sqrt(<4 x fl ; IEEE-BADFREXP-NEXT: [[TMP29:%.*]] = extractvalue { float, i32 } [[TMP28]], 0 ; IEEE-BADFREXP-NEXT: [[TMP30:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float [[TMP4]]) ; IEEE-BADFREXP-NEXT: [[TMP31:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP29]]) -; IEEE-BADFREXP-NEXT: [[TMP32:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float undef) +; IEEE-BADFREXP-NEXT: [[TMP32:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float poison) ; IEEE-BADFREXP-NEXT: [[TMP33:%.*]] = extractvalue { float, i32 } [[TMP32]], 0 -; IEEE-BADFREXP-NEXT: [[TMP34:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float undef) +; IEEE-BADFREXP-NEXT: [[TMP34:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float poison) ; IEEE-BADFREXP-NEXT: [[TMP35:%.*]] = fmul contract float [[TMP33]], [[TMP31]] ; IEEE-BADFREXP-NEXT: [[TMP36:%.*]] = sub i32 [[TMP34]], [[TMP30]] ; IEEE-BADFREXP-NEXT: [[TMP37:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP35]], i32 [[TMP36]]) @@ -3553,7 +3553,7 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_correct_sqrt(<4 x fl ; DAZ-NEXT: [[TMP19:%.*]] = extractvalue { float, i32 } [[TMP18]], 0 ; DAZ-NEXT: [[TMP20:%.*]] = extractvalue { float, i32 } [[TMP18]], 1 ; DAZ-NEXT: [[TMP21:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP19]]) -; DAZ-NEXT: [[TMP22:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float undef) +; DAZ-NEXT: [[TMP22:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float poison) ; DAZ-NEXT: [[TMP23:%.*]] = extractvalue { float, i32 } [[TMP22]], 0 ; DAZ-NEXT: [[TMP24:%.*]] = extractvalue { float, i32 } [[TMP22]], 1 ; DAZ-NEXT: [[TMP25:%.*]] = fmul contract float [[TMP23]], [[TMP21]] @@ -3566,7 +3566,7 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_correct_sqrt(<4 x fl ; DAZ-NEXT: ret <4 x float> [[PARTIAL_RSQ]] ; %denom = call contract <4 x float> @llvm.sqrt.v4f32(<4 x float> %arg) - %partial.rsq = fdiv contract <4 x float> , %denom, !fpmath !2 + %partial.rsq = fdiv contract <4 x float> , %denom, !fpmath !2 ret <4 x float> %partial.rsq } @@ -3607,7 +3607,7 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_arcp(<4 x float> %ar ; IEEE-GOODFREXP-NEXT: [[TMP31:%.*]] = sub i32 0, [[TMP30]] ; IEEE-GOODFREXP-NEXT: [[TMP32:%.*]] = call arcp contract float @llvm.amdgcn.rcp.f32(float [[TMP29]]) ; IEEE-GOODFREXP-NEXT: [[TMP33:%.*]] = call arcp contract float @llvm.ldexp.f32.i32(float [[TMP32]], i32 [[TMP31]]) -; IEEE-GOODFREXP-NEXT: [[TMP34:%.*]] = fmul arcp contract float undef, [[TMP33]] +; IEEE-GOODFREXP-NEXT: [[TMP34:%.*]] = fmul arcp contract float poison, [[TMP33]] ; IEEE-GOODFREXP-NEXT: [[TMP35:%.*]] = insertelement <4 x float> poison, float [[TMP14]], i64 0 ; IEEE-GOODFREXP-NEXT: [[TMP36:%.*]] = insertelement <4 x float> [[TMP35]], float [[TMP20]], i64 1 ; IEEE-GOODFREXP-NEXT: [[TMP37:%.*]] = insertelement <4 x float> [[TMP36]], float [[TMP27]], i64 2 @@ -3650,7 +3650,7 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_arcp(<4 x float> %ar ; IEEE-BADFREXP-NEXT: [[TMP31:%.*]] = sub i32 0, [[TMP30]] ; IEEE-BADFREXP-NEXT: [[TMP32:%.*]] = call arcp contract float @llvm.amdgcn.rcp.f32(float [[TMP29]]) ; IEEE-BADFREXP-NEXT: [[TMP33:%.*]] = call arcp contract float @llvm.ldexp.f32.i32(float [[TMP32]], i32 [[TMP31]]) -; IEEE-BADFREXP-NEXT: [[TMP34:%.*]] = fmul arcp contract float undef, [[TMP33]] +; IEEE-BADFREXP-NEXT: [[TMP34:%.*]] = fmul arcp contract float poison, [[TMP33]] ; IEEE-BADFREXP-NEXT: [[TMP35:%.*]] = insertelement <4 x float> poison, float [[TMP14]], i64 0 ; IEEE-BADFREXP-NEXT: [[TMP36:%.*]] = insertelement <4 x float> [[TMP35]], float [[TMP20]], i64 1 ; IEEE-BADFREXP-NEXT: [[TMP37:%.*]] = insertelement <4 x float> [[TMP36]], float [[TMP27]], i64 2 @@ -3681,7 +3681,7 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_arcp(<4 x float> %ar ; DAZ-NEXT: [[TMP19:%.*]] = call arcp contract float @llvm.amdgcn.rcp.f32(float [[TMP14]]) ; DAZ-NEXT: [[TMP20:%.*]] = fmul arcp contract float 4.000000e+00, [[TMP19]] ; DAZ-NEXT: [[TMP21:%.*]] = call arcp contract float @llvm.amdgcn.rcp.f32(float [[TMP15]]) -; DAZ-NEXT: [[TMP22:%.*]] = fmul arcp contract float undef, [[TMP21]] +; DAZ-NEXT: [[TMP22:%.*]] = fmul arcp contract float poison, [[TMP21]] ; DAZ-NEXT: [[TMP23:%.*]] = insertelement <4 x float> poison, float [[TMP16]], i64 0 ; DAZ-NEXT: [[TMP24:%.*]] = insertelement <4 x float> [[TMP23]], float [[TMP18]], i64 1 ; DAZ-NEXT: [[TMP25:%.*]] = insertelement <4 x float> [[TMP24]], float [[TMP20]], i64 2 @@ -3689,7 +3689,7 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_arcp(<4 x float> %ar ; DAZ-NEXT: ret <4 x float> [[PARTIAL_RSQ]] ; %denom = call contract <4 x float> @llvm.sqrt.v4f32(<4 x float> %arg), !fpmath !2 - %partial.rsq = fdiv contract arcp <4 x float> , %denom, !fpmath !2 + %partial.rsq = fdiv contract arcp <4 x float> , %denom, !fpmath !2 ret <4 x float> %partial.rsq } @@ -3697,7 +3697,7 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_arcp_correct(<4 x fl ; IEEE-LABEL: define <4 x float> @rsq_f32_vector_mixed_constant_numerator_arcp_correct( ; IEEE-SAME: <4 x float> [[ARG:%.*]]) #[[ATTR1]] { ; IEEE-NEXT: [[DENOM:%.*]] = call contract <4 x float> @llvm.sqrt.v4f32(<4 x float> [[ARG]]), !fpmath [[META2]] -; IEEE-NEXT: [[PARTIAL_RSQ:%.*]] = fdiv arcp contract <4 x float> , [[DENOM]] +; IEEE-NEXT: [[PARTIAL_RSQ:%.*]] = fdiv arcp contract <4 x float> , [[DENOM]] ; IEEE-NEXT: ret <4 x float> [[PARTIAL_RSQ]] ; ; DAZ-LABEL: define <4 x float> @rsq_f32_vector_mixed_constant_numerator_arcp_correct( @@ -3714,11 +3714,11 @@ define <4 x float> @rsq_f32_vector_mixed_constant_numerator_arcp_correct(<4 x fl ; DAZ-NEXT: [[TMP10:%.*]] = insertelement <4 x float> [[TMP9]], float [[TMP6]], i64 1 ; DAZ-NEXT: [[TMP11:%.*]] = insertelement <4 x float> [[TMP10]], float [[TMP7]], i64 2 ; DAZ-NEXT: [[DENOM:%.*]] = insertelement <4 x float> [[TMP11]], float [[TMP8]], i64 3 -; DAZ-NEXT: [[PARTIAL_RSQ:%.*]] = fdiv arcp contract <4 x float> , [[DENOM]] +; DAZ-NEXT: [[PARTIAL_RSQ:%.*]] = fdiv arcp contract <4 x float> , [[DENOM]] ; DAZ-NEXT: ret <4 x float> [[PARTIAL_RSQ]] ; %denom = call contract <4 x float> @llvm.sqrt.v4f32(<4 x float> %arg), !fpmath !2 - %partial.rsq = fdiv contract arcp <4 x float> , %denom + %partial.rsq = fdiv contract arcp <4 x float> , %denom ret <4 x float> %partial.rsq } @@ -3755,7 +3755,7 @@ define <4 x float> @rcp_f32_vector_mixed_constant_numerator_arcp(<4 x float> %ar ; IEEE-GOODFREXP-NEXT: [[TMP28:%.*]] = sub i32 0, [[TMP27]] ; IEEE-GOODFREXP-NEXT: [[TMP29:%.*]] = call arcp float @llvm.amdgcn.rcp.f32(float [[TMP26]]) ; IEEE-GOODFREXP-NEXT: [[TMP30:%.*]] = call arcp float @llvm.ldexp.f32.i32(float [[TMP29]], i32 [[TMP28]]) -; IEEE-GOODFREXP-NEXT: [[TMP31:%.*]] = fmul arcp float undef, [[TMP30]] +; IEEE-GOODFREXP-NEXT: [[TMP31:%.*]] = fmul arcp float poison, [[TMP30]] ; IEEE-GOODFREXP-NEXT: [[TMP32:%.*]] = insertelement <4 x float> poison, float [[TMP10]], i64 0 ; IEEE-GOODFREXP-NEXT: [[TMP33:%.*]] = insertelement <4 x float> [[TMP32]], float [[TMP17]], i64 1 ; IEEE-GOODFREXP-NEXT: [[TMP34:%.*]] = insertelement <4 x float> [[TMP33]], float [[TMP24]], i64 2 @@ -3794,7 +3794,7 @@ define <4 x float> @rcp_f32_vector_mixed_constant_numerator_arcp(<4 x float> %ar ; IEEE-BADFREXP-NEXT: [[TMP28:%.*]] = sub i32 0, [[TMP27]] ; IEEE-BADFREXP-NEXT: [[TMP29:%.*]] = call arcp float @llvm.amdgcn.rcp.f32(float [[TMP26]]) ; IEEE-BADFREXP-NEXT: [[TMP30:%.*]] = call arcp float @llvm.ldexp.f32.i32(float [[TMP29]], i32 [[TMP28]]) -; IEEE-BADFREXP-NEXT: [[TMP31:%.*]] = fmul arcp float undef, [[TMP30]] +; IEEE-BADFREXP-NEXT: [[TMP31:%.*]] = fmul arcp float poison, [[TMP30]] ; IEEE-BADFREXP-NEXT: [[TMP32:%.*]] = insertelement <4 x float> poison, float [[TMP10]], i64 0 ; IEEE-BADFREXP-NEXT: [[TMP33:%.*]] = insertelement <4 x float> [[TMP32]], float [[TMP17]], i64 1 ; IEEE-BADFREXP-NEXT: [[TMP34:%.*]] = insertelement <4 x float> [[TMP33]], float [[TMP24]], i64 2 @@ -3813,24 +3813,24 @@ define <4 x float> @rcp_f32_vector_mixed_constant_numerator_arcp(<4 x float> %ar ; DAZ-NEXT: [[TMP8:%.*]] = call arcp float @llvm.amdgcn.rcp.f32(float [[TMP3]]) ; DAZ-NEXT: [[TMP9:%.*]] = fmul arcp float 4.000000e+00, [[TMP8]] ; DAZ-NEXT: [[TMP10:%.*]] = call arcp float @llvm.amdgcn.rcp.f32(float [[TMP4]]) -; DAZ-NEXT: [[TMP11:%.*]] = fmul arcp float undef, [[TMP10]] +; DAZ-NEXT: [[TMP11:%.*]] = fmul arcp float poison, [[TMP10]] ; DAZ-NEXT: [[TMP12:%.*]] = insertelement <4 x float> poison, float [[TMP5]], i64 0 ; DAZ-NEXT: [[TMP13:%.*]] = insertelement <4 x float> [[TMP12]], float [[TMP7]], i64 1 ; DAZ-NEXT: [[TMP14:%.*]] = insertelement <4 x float> [[TMP13]], float [[TMP9]], i64 2 ; DAZ-NEXT: [[PARTIAL_RCP:%.*]] = insertelement <4 x float> [[TMP14]], float [[TMP11]], i64 3 ; DAZ-NEXT: ret <4 x float> [[PARTIAL_RCP]] ; - %partial.rcp = fdiv arcp <4 x float> , %arg, !fpmath !2 + %partial.rcp = fdiv arcp <4 x float> , %arg, !fpmath !2 ret <4 x float> %partial.rcp } define <4 x float> @rcp_f32_vector_mixed_constant_numerator_arcp_correct(<4 x float> %arg) { ; CHECK-LABEL: define <4 x float> @rcp_f32_vector_mixed_constant_numerator_arcp_correct( ; CHECK-SAME: <4 x float> [[ARG:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[PARTIAL_RCP:%.*]] = fdiv arcp <4 x float> , [[ARG]] +; CHECK-NEXT: [[PARTIAL_RCP:%.*]] = fdiv arcp <4 x float> , [[ARG]] ; CHECK-NEXT: ret <4 x float> [[PARTIAL_RCP]] ; - %partial.rcp = fdiv arcp <4 x float> , %arg + %partial.rcp = fdiv arcp <4 x float> , %arg ret <4 x float> %partial.rcp } @@ -3841,7 +3841,7 @@ define <4 x float> @rsq_f32_vector_const_denom(ptr addrspace(1) %out, <2 x float ; IEEE-GOODFREXP-NEXT: [[TMP1:%.*]] = call float @llvm.amdgcn.sqrt.f32(float 4.000000e+00) ; IEEE-GOODFREXP-NEXT: [[TMP2:%.*]] = call float @llvm.amdgcn.sqrt.f32(float 2.000000e+00) ; IEEE-GOODFREXP-NEXT: [[TMP3:%.*]] = call float @llvm.amdgcn.sqrt.f32(float 8.000000e+00) -; IEEE-GOODFREXP-NEXT: [[TMP4:%.*]] = call float @llvm.amdgcn.sqrt.f32(float undef) +; IEEE-GOODFREXP-NEXT: [[TMP4:%.*]] = call float @llvm.amdgcn.sqrt.f32(float poison) ; IEEE-GOODFREXP-NEXT: [[TMP5:%.*]] = insertelement <4 x float> poison, float [[TMP1]], i64 0 ; IEEE-GOODFREXP-NEXT: [[TMP6:%.*]] = insertelement <4 x float> [[TMP5]], float [[TMP2]], i64 1 ; IEEE-GOODFREXP-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[TMP6]], float [[TMP3]], i64 2 @@ -3857,21 +3857,21 @@ define <4 x float> @rsq_f32_vector_const_denom(ptr addrspace(1) %out, <2 x float ; IEEE-GOODFREXP-NEXT: [[TMP16:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP13]]) ; IEEE-GOODFREXP-NEXT: [[TMP17:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP16]], i32 [[TMP15]]) ; IEEE-GOODFREXP-NEXT: [[TMP18:%.*]] = fneg contract float [[TMP9]] -; IEEE-GOODFREXP-NEXT: [[TMP25:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[TMP18]]) -; IEEE-GOODFREXP-NEXT: [[TMP26:%.*]] = extractvalue { float, i32 } [[TMP25]], 0 -; IEEE-GOODFREXP-NEXT: [[TMP27:%.*]] = extractvalue { float, i32 } [[TMP25]], 1 -; IEEE-GOODFREXP-NEXT: [[TMP22:%.*]] = sub i32 0, [[TMP27]] -; IEEE-GOODFREXP-NEXT: [[TMP28:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP26]]) -; IEEE-GOODFREXP-NEXT: [[TMP24:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP28]], i32 [[TMP22]]) -; IEEE-GOODFREXP-NEXT: [[TMP48:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[TMP10]]) +; IEEE-GOODFREXP-NEXT: [[TMP48:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[TMP18]]) ; IEEE-GOODFREXP-NEXT: [[TMP49:%.*]] = extractvalue { float, i32 } [[TMP48]], 0 ; IEEE-GOODFREXP-NEXT: [[TMP50:%.*]] = extractvalue { float, i32 } [[TMP48]], 1 +; IEEE-GOODFREXP-NEXT: [[TMP22:%.*]] = sub i32 0, [[TMP50]] ; IEEE-GOODFREXP-NEXT: [[TMP51:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP49]]) -; IEEE-GOODFREXP-NEXT: [[TMP29:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float undef) +; IEEE-GOODFREXP-NEXT: [[TMP24:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP51]], i32 [[TMP22]]) +; IEEE-GOODFREXP-NEXT: [[TMP29:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[TMP10]]) ; IEEE-GOODFREXP-NEXT: [[TMP30:%.*]] = extractvalue { float, i32 } [[TMP29]], 0 ; IEEE-GOODFREXP-NEXT: [[TMP31:%.*]] = extractvalue { float, i32 } [[TMP29]], 1 -; IEEE-GOODFREXP-NEXT: [[TMP32:%.*]] = fmul contract float [[TMP30]], [[TMP51]] -; IEEE-GOODFREXP-NEXT: [[TMP33:%.*]] = sub i32 [[TMP31]], [[TMP50]] +; IEEE-GOODFREXP-NEXT: [[TMP28:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP30]]) +; IEEE-GOODFREXP-NEXT: [[TMP52:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float poison) +; IEEE-GOODFREXP-NEXT: [[TMP53:%.*]] = extractvalue { float, i32 } [[TMP52]], 0 +; IEEE-GOODFREXP-NEXT: [[TMP54:%.*]] = extractvalue { float, i32 } [[TMP52]], 1 +; IEEE-GOODFREXP-NEXT: [[TMP32:%.*]] = fmul contract float [[TMP53]], [[TMP28]] +; IEEE-GOODFREXP-NEXT: [[TMP33:%.*]] = sub i32 [[TMP54]], [[TMP31]] ; IEEE-GOODFREXP-NEXT: [[TMP34:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP32]], i32 [[TMP33]]) ; IEEE-GOODFREXP-NEXT: [[TMP35:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[TMP11]]) ; IEEE-GOODFREXP-NEXT: [[TMP36:%.*]] = extractvalue { float, i32 } [[TMP35]], 0 @@ -3894,7 +3894,7 @@ define <4 x float> @rsq_f32_vector_const_denom(ptr addrspace(1) %out, <2 x float ; IEEE-BADFREXP-NEXT: [[TMP1:%.*]] = call float @llvm.amdgcn.sqrt.f32(float 4.000000e+00) ; IEEE-BADFREXP-NEXT: [[TMP2:%.*]] = call float @llvm.amdgcn.sqrt.f32(float 2.000000e+00) ; IEEE-BADFREXP-NEXT: [[TMP3:%.*]] = call float @llvm.amdgcn.sqrt.f32(float 8.000000e+00) -; IEEE-BADFREXP-NEXT: [[TMP4:%.*]] = call float @llvm.amdgcn.sqrt.f32(float undef) +; IEEE-BADFREXP-NEXT: [[TMP4:%.*]] = call float @llvm.amdgcn.sqrt.f32(float poison) ; IEEE-BADFREXP-NEXT: [[TMP5:%.*]] = insertelement <4 x float> poison, float [[TMP1]], i64 0 ; IEEE-BADFREXP-NEXT: [[TMP6:%.*]] = insertelement <4 x float> [[TMP5]], float [[TMP2]], i64 1 ; IEEE-BADFREXP-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[TMP6]], float [[TMP3]], i64 2 @@ -3910,20 +3910,20 @@ define <4 x float> @rsq_f32_vector_const_denom(ptr addrspace(1) %out, <2 x float ; IEEE-BADFREXP-NEXT: [[TMP16:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP13]]) ; IEEE-BADFREXP-NEXT: [[TMP17:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP16]], i32 [[TMP15]]) ; IEEE-BADFREXP-NEXT: [[TMP18:%.*]] = fneg contract float [[TMP9]] -; IEEE-BADFREXP-NEXT: [[TMP25:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[TMP18]]) -; IEEE-BADFREXP-NEXT: [[TMP26:%.*]] = extractvalue { float, i32 } [[TMP25]], 0 +; IEEE-BADFREXP-NEXT: [[TMP48:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[TMP18]]) +; IEEE-BADFREXP-NEXT: [[TMP49:%.*]] = extractvalue { float, i32 } [[TMP48]], 0 ; IEEE-BADFREXP-NEXT: [[TMP21:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float [[TMP18]]) ; IEEE-BADFREXP-NEXT: [[TMP22:%.*]] = sub i32 0, [[TMP21]] -; IEEE-BADFREXP-NEXT: [[TMP28:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP26]]) -; IEEE-BADFREXP-NEXT: [[TMP24:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP28]], i32 [[TMP22]]) -; IEEE-BADFREXP-NEXT: [[TMP48:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[TMP10]]) -; IEEE-BADFREXP-NEXT: [[TMP49:%.*]] = extractvalue { float, i32 } [[TMP48]], 0 -; IEEE-BADFREXP-NEXT: [[TMP27:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float [[TMP10]]) ; IEEE-BADFREXP-NEXT: [[TMP50:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP49]]) -; IEEE-BADFREXP-NEXT: [[TMP29:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float undef) +; IEEE-BADFREXP-NEXT: [[TMP24:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP50]], i32 [[TMP22]]) +; IEEE-BADFREXP-NEXT: [[TMP29:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[TMP10]]) ; IEEE-BADFREXP-NEXT: [[TMP30:%.*]] = extractvalue { float, i32 } [[TMP29]], 0 -; IEEE-BADFREXP-NEXT: [[TMP31:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float undef) -; IEEE-BADFREXP-NEXT: [[TMP32:%.*]] = fmul contract float [[TMP30]], [[TMP50]] +; IEEE-BADFREXP-NEXT: [[TMP27:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float [[TMP10]]) +; IEEE-BADFREXP-NEXT: [[TMP28:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP30]]) +; IEEE-BADFREXP-NEXT: [[TMP51:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float poison) +; IEEE-BADFREXP-NEXT: [[TMP52:%.*]] = extractvalue { float, i32 } [[TMP51]], 0 +; IEEE-BADFREXP-NEXT: [[TMP31:%.*]] = call i32 @llvm.amdgcn.frexp.exp.i32.f32(float poison) +; IEEE-BADFREXP-NEXT: [[TMP32:%.*]] = fmul contract float [[TMP52]], [[TMP28]] ; IEEE-BADFREXP-NEXT: [[TMP33:%.*]] = sub i32 [[TMP31]], [[TMP27]] ; IEEE-BADFREXP-NEXT: [[TMP34:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP32]], i32 [[TMP33]]) ; IEEE-BADFREXP-NEXT: [[TMP35:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[TMP11]]) @@ -3947,7 +3947,7 @@ define <4 x float> @rsq_f32_vector_const_denom(ptr addrspace(1) %out, <2 x float ; DAZ-NEXT: [[TMP1:%.*]] = call float @llvm.amdgcn.sqrt.f32(float 4.000000e+00) ; DAZ-NEXT: [[TMP2:%.*]] = call float @llvm.amdgcn.sqrt.f32(float 2.000000e+00) ; DAZ-NEXT: [[TMP3:%.*]] = call float @llvm.amdgcn.sqrt.f32(float 8.000000e+00) -; DAZ-NEXT: [[TMP4:%.*]] = call float @llvm.amdgcn.sqrt.f32(float undef) +; DAZ-NEXT: [[TMP4:%.*]] = call float @llvm.amdgcn.sqrt.f32(float poison) ; DAZ-NEXT: [[TMP5:%.*]] = insertelement <4 x float> poison, float [[TMP1]], i64 0 ; DAZ-NEXT: [[TMP6:%.*]] = insertelement <4 x float> [[TMP5]], float [[TMP2]], i64 1 ; DAZ-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[TMP6]], float [[TMP3]], i64 2 @@ -3963,7 +3963,7 @@ define <4 x float> @rsq_f32_vector_const_denom(ptr addrspace(1) %out, <2 x float ; DAZ-NEXT: [[TMP16:%.*]] = extractvalue { float, i32 } [[TMP15]], 0 ; DAZ-NEXT: [[TMP17:%.*]] = extractvalue { float, i32 } [[TMP15]], 1 ; DAZ-NEXT: [[TMP18:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[TMP16]]) -; DAZ-NEXT: [[TMP19:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float undef) +; DAZ-NEXT: [[TMP19:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float poison) ; DAZ-NEXT: [[TMP20:%.*]] = extractvalue { float, i32 } [[TMP19]], 0 ; DAZ-NEXT: [[TMP21:%.*]] = extractvalue { float, i32 } [[TMP19]], 1 ; DAZ-NEXT: [[TMP22:%.*]] = fmul contract float [[TMP20]], [[TMP18]] @@ -3985,8 +3985,8 @@ define <4 x float> @rsq_f32_vector_const_denom(ptr addrspace(1) %out, <2 x float ; DAZ-NEXT: [[PARTIAL_RSQ:%.*]] = insertelement <4 x float> [[TMP37]], float [[TMP34]], i64 3 ; DAZ-NEXT: ret <4 x float> [[PARTIAL_RSQ]] ; - %sqrt = call contract <4 x float> @llvm.sqrt.v4f32(<4 x float> ), !fpmath !2 - %partial.rsq = fdiv contract <4 x float> , %sqrt, !fpmath !2 + %sqrt = call contract <4 x float> @llvm.sqrt.v4f32(<4 x float> ), !fpmath !2 + %partial.rsq = fdiv contract <4 x float> , %sqrt, !fpmath !2 ret <4 x float> %partial.rsq } diff --git a/llvm/test/Transforms/Attributor/nofpclass.ll b/llvm/test/Transforms/Attributor/nofpclass.ll index 5945fc5e7b0b..b38f9bae50cc 100644 --- a/llvm/test/Transforms/Attributor/nofpclass.ll +++ b/llvm/test/Transforms/Attributor/nofpclass.ll @@ -114,7 +114,7 @@ define <2 x double> @returned_strange_constant_vector_elt() { ; Test a vector element that's undef define <3 x double> @returned_undef_constant_vector_elt() { -; CHECK-LABEL: define nofpclass(nan inf sub norm) <3 x double> @returned_undef_constant_vector_elt() { +; CHECK-LABEL: define <3 x double> @returned_undef_constant_vector_elt() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret <3 x double> ; diff --git a/llvm/test/Transforms/InstCombine/and-fcmp.ll b/llvm/test/Transforms/InstCombine/and-fcmp.ll index f1ae2e74ac2e..c163802fcc93 100644 --- a/llvm/test/Transforms/InstCombine/and-fcmp.ll +++ b/llvm/test/Transforms/InstCombine/and-fcmp.ll @@ -39,7 +39,9 @@ define i1 @PR1738_logical_noundef(double %x, double noundef %y) { define <2 x i1> @PR1738_vec_undef(<2 x double> %x, <2 x double> %y) { ; CHECK-LABEL: @PR1738_vec_undef( -; CHECK-NEXT: [[OR:%.*]] = fcmp ord <2 x double> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord <2 x double> [[X:%.*]], +; CHECK-NEXT: [[CMP2:%.*]] = fcmp ord <2 x double> [[Y:%.*]], +; CHECK-NEXT: [[OR:%.*]] = and <2 x i1> [[CMP1]], [[CMP2]] ; CHECK-NEXT: ret <2 x i1> [[OR]] ; %cmp1 = fcmp ord <2 x double> %x, @@ -48,6 +50,17 @@ define <2 x i1> @PR1738_vec_undef(<2 x double> %x, <2 x double> %y) { ret <2 x i1> %or } +define <2 x i1> @PR1738_vec_poison(<2 x double> %x, <2 x double> %y) { +; CHECK-LABEL: @PR1738_vec_poison( +; CHECK-NEXT: [[OR:%.*]] = fcmp ord <2 x double> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret <2 x i1> [[OR]] +; + %cmp1 = fcmp ord <2 x double> %x, + %cmp2 = fcmp ord <2 x double> %y, + %or = and <2 x i1> %cmp1, %cmp2 + ret <2 x i1> %or +} + define i1 @PR41069(i1 %z, float %c, float %d) { ; CHECK-LABEL: @PR41069( ; CHECK-NEXT: [[TMP1:%.*]] = fcmp ord float [[D:%.*]], [[C:%.*]] @@ -111,8 +124,10 @@ define i1 @PR41069_commute_logical(i1 %z, float %c, float %d) { define <2 x i1> @PR41069_vec(<2 x double> %a, <2 x double> %b, <2 x double> %c, <2 x double> %d) { ; CHECK-LABEL: @PR41069_vec( ; CHECK-NEXT: [[ORD1:%.*]] = fcmp ord <2 x double> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = fcmp ord <2 x double> [[D:%.*]], [[C:%.*]] -; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[TMP1]], [[ORD1]] +; CHECK-NEXT: [[ORD2:%.*]] = fcmp ord <2 x double> [[C:%.*]], +; CHECK-NEXT: [[AND:%.*]] = and <2 x i1> [[ORD1]], [[ORD2]] +; CHECK-NEXT: [[ORD3:%.*]] = fcmp ord <2 x double> [[D:%.*]], zeroinitializer +; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[AND]], [[ORD3]] ; CHECK-NEXT: ret <2 x i1> [[R]] ; %ord1 = fcmp ord <2 x double> %a, %b @@ -126,8 +141,10 @@ define <2 x i1> @PR41069_vec(<2 x double> %a, <2 x double> %b, <2 x double> %c, define <2 x i1> @PR41069_vec_commute(<2 x double> %a, <2 x double> %b, <2 x double> %c, <2 x double> %d) { ; CHECK-LABEL: @PR41069_vec_commute( ; CHECK-NEXT: [[ORD1:%.*]] = fcmp ord <2 x double> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = fcmp ord <2 x double> [[D:%.*]], [[C:%.*]] -; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[TMP1]], [[ORD1]] +; CHECK-NEXT: [[ORD2:%.*]] = fcmp ord <2 x double> [[C:%.*]], +; CHECK-NEXT: [[AND:%.*]] = and <2 x i1> [[ORD1]], [[ORD2]] +; CHECK-NEXT: [[ORD3:%.*]] = fcmp ord <2 x double> [[D:%.*]], zeroinitializer +; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[ORD3]], [[AND]] ; CHECK-NEXT: ret <2 x i1> [[R]] ; %ord1 = fcmp ord <2 x double> %a, %b diff --git a/llvm/test/Transforms/InstCombine/or-fcmp.ll b/llvm/test/Transforms/InstCombine/or-fcmp.ll index ffd927672b41..285b2d958abd 100644 --- a/llvm/test/Transforms/InstCombine/or-fcmp.ll +++ b/llvm/test/Transforms/InstCombine/or-fcmp.ll @@ -28,7 +28,9 @@ define i1 @PR1738_logical(double %x, double %y) { define <2 x i1> @PR1738_vec_undef(<2 x double> %x, <2 x double> %y) { ; CHECK-LABEL: @PR1738_vec_undef( -; CHECK-NEXT: [[OR:%.*]] = fcmp uno <2 x double> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno <2 x double> [[X:%.*]], +; CHECK-NEXT: [[CMP2:%.*]] = fcmp uno <2 x double> [[Y:%.*]], +; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[CMP1]], [[CMP2]] ; CHECK-NEXT: ret <2 x i1> [[OR]] ; %cmp1 = fcmp uno <2 x double> %x, @@ -37,6 +39,17 @@ define <2 x i1> @PR1738_vec_undef(<2 x double> %x, <2 x double> %y) { ret <2 x i1> %or } +define <2 x i1> @PR1738_vec_poison(<2 x double> %x, <2 x double> %y) { +; CHECK-LABEL: @PR1738_vec_poison( +; CHECK-NEXT: [[OR:%.*]] = fcmp uno <2 x double> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret <2 x i1> [[OR]] +; + %cmp1 = fcmp uno <2 x double> %x, + %cmp2 = fcmp uno <2 x double> %y, + %or = or <2 x i1> %cmp1, %cmp2 + ret <2 x i1> %or +} + define i1 @PR41069(double %a, double %b, double %c, double %d) { ; CHECK-LABEL: @PR41069( ; CHECK-NEXT: [[UNO1:%.*]] = fcmp uno double [[A:%.*]], [[B:%.*]] @@ -105,26 +118,56 @@ define i1 @PR41069_commute_logical(double %a, double %b, double %c, double %d) { define <2 x i1> @PR41069_vec(<2 x i1> %z, <2 x float> %c, <2 x float> %d) { ; CHECK-LABEL: @PR41069_vec( +; CHECK-NEXT: [[UNO1:%.*]] = fcmp uno <2 x float> [[C:%.*]], zeroinitializer +; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[UNO1]], [[Z:%.*]] +; CHECK-NEXT: [[UNO2:%.*]] = fcmp uno <2 x float> [[D:%.*]], +; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[OR]], [[UNO2]] +; CHECK-NEXT: ret <2 x i1> [[R]] +; + %uno1 = fcmp uno <2 x float> %c, zeroinitializer + %or = or <2 x i1> %uno1, %z + %uno2 = fcmp uno <2 x float> %d, + %r = or <2 x i1> %or, %uno2 + ret <2 x i1> %r +} + +define <2 x i1> @PR41069_vec_poison(<2 x i1> %z, <2 x float> %c, <2 x float> %d) { +; CHECK-LABEL: @PR41069_vec_poison( ; CHECK-NEXT: [[TMP1:%.*]] = fcmp uno <2 x float> [[D:%.*]], [[C:%.*]] ; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[TMP1]], [[Z:%.*]] ; CHECK-NEXT: ret <2 x i1> [[R]] ; %uno1 = fcmp uno <2 x float> %c, zeroinitializer %or = or <2 x i1> %uno1, %z - %uno2 = fcmp uno <2 x float> %d, + %uno2 = fcmp uno <2 x float> %d, %r = or <2 x i1> %or, %uno2 ret <2 x i1> %r } define <2 x i1> @PR41069_vec_commute(<2 x i1> %z, <2 x float> %c, <2 x float> %d) { ; CHECK-LABEL: @PR41069_vec_commute( +; CHECK-NEXT: [[UNO1:%.*]] = fcmp uno <2 x float> [[C:%.*]], zeroinitializer +; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[UNO1]], [[Z:%.*]] +; CHECK-NEXT: [[UNO2:%.*]] = fcmp uno <2 x float> [[D:%.*]], +; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[UNO2]], [[OR]] +; CHECK-NEXT: ret <2 x i1> [[R]] +; + %uno1 = fcmp uno <2 x float> %c, zeroinitializer + %or = or <2 x i1> %uno1, %z + %uno2 = fcmp uno <2 x float> %d, + %r = or <2 x i1> %uno2, %or + ret <2 x i1> %r +} + +define <2 x i1> @PR41069_vec_commute_poison(<2 x i1> %z, <2 x float> %c, <2 x float> %d) { +; CHECK-LABEL: @PR41069_vec_commute_poison( ; CHECK-NEXT: [[TMP1:%.*]] = fcmp uno <2 x float> [[D:%.*]], [[C:%.*]] ; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[TMP1]], [[Z:%.*]] ; CHECK-NEXT: ret <2 x i1> [[R]] ; %uno1 = fcmp uno <2 x float> %c, zeroinitializer %or = or <2 x i1> %uno1, %z - %uno2 = fcmp uno <2 x float> %d, + %uno2 = fcmp uno <2 x float> %d, %r = or <2 x i1> %uno2, %or ret <2 x i1> %r } -- GitLab From 878642954f5178c55b337afe2bff4e6a92a67a5b Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Sun, 19 May 2024 13:23:04 -0700 Subject: [PATCH 035/793] [BOLT] Fix preserved offset in fixDoubleJumps (#92485) --- bolt/lib/Passes/BinaryPasses.cpp | 14 +++++++++----- bolt/test/X86/bb-with-two-tail-calls.s | 8 ++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp index 867f977cebca..298ba29ff5b3 100644 --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -674,7 +674,8 @@ static uint64_t fixDoubleJumps(BinaryFunction &Function, bool MarkInvalid) { MCPlusBuilder *MIB = Function.getBinaryContext().MIB.get(); for (BinaryBasicBlock &BB : Function) { auto checkAndPatch = [&](BinaryBasicBlock *Pred, BinaryBasicBlock *Succ, - const MCSymbol *SuccSym) { + const MCSymbol *SuccSym, + std::optional Offset) { // Ignore infinite loop jumps or fallthrough tail jumps. if (Pred == Succ || Succ == &BB) return false; @@ -715,9 +716,11 @@ static uint64_t fixDoubleJumps(BinaryFunction &Function, bool MarkInvalid) { Pred->removeSuccessor(&BB); Pred->eraseInstruction(Pred->findInstruction(Branch)); Pred->addTailCallInstruction(SuccSym); - MCInst *TailCall = Pred->getLastNonPseudoInstr(); - assert(TailCall); - MIB->setOffset(*TailCall, BB.getOffset()); + if (Offset) { + MCInst *TailCall = Pred->getLastNonPseudoInstr(); + assert(TailCall); + MIB->setOffset(*TailCall, *Offset); + } } else { return false; } @@ -760,7 +763,8 @@ static uint64_t fixDoubleJumps(BinaryFunction &Function, bool MarkInvalid) { if (Pred->getSuccessor() == &BB || (Pred->getConditionalSuccessor(true) == &BB && !IsTailCall) || Pred->getConditionalSuccessor(false) == &BB) - if (checkAndPatch(Pred, Succ, SuccSym) && MarkInvalid) + if (checkAndPatch(Pred, Succ, SuccSym, MIB->getOffset(*Inst)) && + MarkInvalid) BB.markValid(BB.pred_size() != 0 || BB.isLandingPad() || BB.isEntryPoint()); } diff --git a/bolt/test/X86/bb-with-two-tail-calls.s b/bolt/test/X86/bb-with-two-tail-calls.s index bb2b0cd4cc23..b6703e352ff4 100644 --- a/bolt/test/X86/bb-with-two-tail-calls.s +++ b/bolt/test/X86/bb-with-two-tail-calls.s @@ -1,8 +1,6 @@ # This reproduces a bug with dynostats when trying to compute branch stats # at a block with two tails calls (one conditional and one unconditional). -# REQUIRES: system-linux - # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \ # RUN: %s -o %t.o # RUN: link_fdata %s %t.o %t.fdata @@ -13,7 +11,7 @@ # CHECK-NOT: Assertion `BranchInfo.size() == 2 && "could only be called for blocks with 2 successors"' failed. # Two tail calls in the same basic block after SCTC: # CHECK: {{.*}}: ja {{.*}} # TAILCALL # Offset: 7 # CTCTakenCount: 4 -# CHECK-NEXT: {{.*}}: jmp {{.*}} # TAILCALL # Offset: 12 +# CHECK-NEXT: {{.*}}: jmp {{.*}} # TAILCALL # Offset: 13 .globl _start _start: @@ -23,7 +21,9 @@ a: ja b x: ret # FDATA: 1 _start #a# 1 _start #b# 2 4 b: jmp e -c: jmp f +c: + .nops 1 + jmp f .globl e e: -- GitLab From fb2c6597e39e9e1a775525ea0236b2f89e46acff Mon Sep 17 00:00:00 2001 From: Leon Clark Date: Sun, 19 May 2024 21:45:24 +0100 Subject: [PATCH 036/793] [AMDGPU] Use LSH for lowering ctlz_zero_undef.i8/i16 (#88512) Use LSH to lower ctlz_zero_undef instead of subtracting leading zeros for i8 and i16. Related to [77615](https://github.com/llvm/llvm-project/pull/77615). --------- Co-authored-by: Leon Clark --- llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp | 22 +- .../lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp | 44 +++- llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h | 2 + .../GlobalISel/legalize-ctlz-zero-undef.mir | 47 ++-- llvm/test/CodeGen/AMDGPU/ctlz_zero_undef.ll | 232 +++++++----------- 5 files changed, 169 insertions(+), 178 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp index d35a022ad680..980e58510ceb 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp @@ -3117,20 +3117,30 @@ static bool isCttzOpc(unsigned Opc) { SDValue AMDGPUTargetLowering::lowerCTLZResults(SDValue Op, SelectionDAG &DAG) const { auto SL = SDLoc(Op); + auto Opc = Op.getOpcode(); auto Arg = Op.getOperand(0u); auto ResultVT = Op.getValueType(); if (ResultVT != MVT::i8 && ResultVT != MVT::i16) return {}; - assert(isCtlzOpc(Op.getOpcode())); + assert(isCtlzOpc(Opc)); 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); - NewOp = DAG.getNode(Op.getOpcode(), SL, MVT::i32, NewOp); - NewOp = DAG.getNode(ISD::SUB, SL, MVT::i32, NewOp, SubVal); + const uint64_t NumBits = ResultVT.getFixedSizeInBits(); + SDValue NumExtBits = DAG.getConstant(32u - NumBits, SL, MVT::i32); + SDValue NewOp; + + if (Opc == ISD::CTLZ_ZERO_UNDEF) { + NewOp = DAG.getNode(ISD::ANY_EXTEND, SL, MVT::i32, Arg); + NewOp = DAG.getNode(ISD::SHL, SL, MVT::i32, NewOp, NumExtBits); + NewOp = DAG.getNode(Opc, SL, MVT::i32, NewOp); + } else { + NewOp = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Arg); + NewOp = DAG.getNode(Opc, SL, MVT::i32, NewOp); + NewOp = DAG.getNode(ISD::SUB, SL, MVT::i32, NewOp, NumExtBits); + } + return DAG.getNode(ISD::TRUNCATE, SL, ResultVT, NewOp); } diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp index bd7bf78c4c0b..15a4b6796880 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -1270,13 +1270,22 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_, .custom(); // The 64-bit versions produce 32-bit results, but only on the SALU. - getActionDefinitionsBuilder({G_CTLZ_ZERO_UNDEF, G_CTTZ_ZERO_UNDEF}) - .legalFor({{S32, S32}, {S32, S64}}) - .clampScalar(0, S32, S32) - .clampScalar(1, S32, S64) - .scalarize(0) - .widenScalarToNextPow2(0, 32) - .widenScalarToNextPow2(1, 32); + getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF) + .legalFor({{S32, S32}, {S32, S64}}) + .customIf(scalarNarrowerThan(1, 32)) + .clampScalar(0, S32, S32) + .clampScalar(1, S32, S64) + .scalarize(0) + .widenScalarToNextPow2(0, 32) + .widenScalarToNextPow2(1, 32); + + getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF) + .legalFor({{S32, S32}, {S32, S64}}) + .clampScalar(0, S32, S32) + .clampScalar(1, S32, S64) + .scalarize(0) + .widenScalarToNextPow2(0, 32) + .widenScalarToNextPow2(1, 32); // S64 is only legal on SALU, and needs to be broken into 32-bit elements in // RegBankSelect. @@ -2128,6 +2137,8 @@ bool AMDGPULegalizerInfo::legalizeCustom( case TargetOpcode::G_CTLZ: case TargetOpcode::G_CTTZ: return legalizeCTLZ_CTTZ(MI, MRI, B); + case TargetOpcode::G_CTLZ_ZERO_UNDEF: + return legalizeCTLZ_ZERO_UNDEF(MI, MRI, B); case TargetOpcode::G_INTRINSIC_FPTRUNC_ROUND: return legalizeFPTruncRound(MI, B); case TargetOpcode::G_STACKSAVE: @@ -4145,6 +4156,25 @@ bool AMDGPULegalizerInfo::legalizeCTLZ_CTTZ(MachineInstr &MI, return true; } +bool AMDGPULegalizerInfo::legalizeCTLZ_ZERO_UNDEF(MachineInstr &MI, + MachineRegisterInfo &MRI, + MachineIRBuilder &B) const { + Register Dst = MI.getOperand(0).getReg(); + Register Src = MI.getOperand(1).getReg(); + LLT SrcTy = MRI.getType(Src); + TypeSize NumBits = SrcTy.getSizeInBits(); + + assert(NumBits < 32u); + + auto ShiftAmt = B.buildConstant(S32, 32u - NumBits); + auto Extend = B.buildAnyExt(S32, {Src}).getReg(0u); + auto Shift = B.buildLShr(S32, {Extend}, ShiftAmt); + auto Ctlz = B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {S32}, {Shift}); + B.buildTrunc(Dst, Ctlz); + MI.eraseFromParent(); + return true; +} + // Check that this is a G_XOR x, -1 static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI) { if (MI.getOpcode() != TargetOpcode::G_XOR) diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h index e5ba84a74a0f..4b1d821dadc2 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h +++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h @@ -108,6 +108,8 @@ public: bool legalizeMul(LegalizerHelper &Helper, MachineInstr &MI) const; bool legalizeCTLZ_CTTZ(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const; + bool legalizeCTLZ_ZERO_UNDEF(MachineInstr &MI, MachineRegisterInfo &MRI, + MachineIRBuilder &B) const; bool loadInputValue(Register DstReg, MachineIRBuilder &B, const ArgDescriptor *Arg, diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ctlz-zero-undef.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ctlz-zero-undef.mir index fed277d7d10d..7748b481cf5b 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ctlz-zero-undef.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ctlz-zero-undef.mir @@ -81,14 +81,12 @@ body: | ; CHECK: liveins: $vgpr0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 - ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]] - ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[AND]](s32) - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 - ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[CTLZ_ZERO_UNDEF]], [[C1]] - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY [[SUB]](s32) - ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY1]], [[C]] - ; CHECK-NEXT: $vgpr0 = COPY [[AND1]](s32) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[COPY]], [[C]](s32) + ; CHECK-NEXT: [[AMDGPU_FFBH_U32:%[0-9]+]]:_(s32) = G_AMDGPU_FFBH_U32 [[LSHR]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[AMDGPU_FFBH_U32]], [[C1]] + ; CHECK-NEXT: $vgpr0 = COPY [[AND]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s16) = G_TRUNC %0 %2:_(s16) = G_CTLZ_ZERO_UNDEF %1 @@ -149,18 +147,15 @@ body: | ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(s32) = G_BITCAST [[COPY]](<2 x s16>) ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[BITCAST]], [[C]](s32) + ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(s32) = G_LSHR [[BITCAST]], [[C]](s32) + ; CHECK-NEXT: [[AMDGPU_FFBH_U32:%[0-9]+]]:_(s32) = G_AMDGPU_FFBH_U32 [[LSHR1]](s32) + ; CHECK-NEXT: [[LSHR2:%[0-9]+]]:_(s32) = G_LSHR [[LSHR]], [[C]](s32) + ; CHECK-NEXT: [[AMDGPU_FFBH_U321:%[0-9]+]]:_(s32) = G_AMDGPU_FFBH_U32 [[LSHR2]](s32) ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 - ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[BITCAST]], [[C1]] - ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[AND]](s32) - ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[CTLZ_ZERO_UNDEF]], [[C]] - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY [[SUB]](s32) - ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF1:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[LSHR]](s32) - ; CHECK-NEXT: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[CTLZ_ZERO_UNDEF1]], [[C]] - ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY [[SUB1]](s32) - ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY1]], [[C1]] - ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C1]] - ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[AND2]], [[C]](s32) - ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[AND1]], [[SHL]] + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[AMDGPU_FFBH_U32]], [[C1]] + ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[AMDGPU_FFBH_U321]], [[C1]] + ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[AND1]], [[C]](s32) + ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[AND]], [[SHL]] ; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[OR]](s32) ; CHECK-NEXT: $vgpr0 = COPY [[BITCAST1]](<2 x s16>) %0:_(<2 x s16>) = COPY $vgpr0 @@ -179,14 +174,12 @@ body: | ; CHECK: liveins: $vgpr0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 127 - ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]] - ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[AND]](s32) - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 25 - ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[CTLZ_ZERO_UNDEF]], [[C1]] - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY [[SUB]](s32) - ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY1]], [[C]] - ; CHECK-NEXT: $vgpr0 = COPY [[AND1]](s32) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 25 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[COPY]], [[C]](s32) + ; CHECK-NEXT: [[FFBH:%[0-9]+]]:_(s32) = G_AMDGPU_FFBH_U32 [[LSHR]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 127 + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[FFBH]], [[C1]] + ; CHECK-NEXT: $vgpr0 = COPY [[AND]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s7) = G_TRUNC %0 %2:_(s7) = G_CTLZ_ZERO_UNDEF %1 diff --git a/llvm/test/CodeGen/AMDGPU/ctlz_zero_undef.ll b/llvm/test/CodeGen/AMDGPU/ctlz_zero_undef.ll index 54adde38d6d2..d94a27e8c020 100644 --- a/llvm/test/CodeGen/AMDGPU/ctlz_zero_undef.ll +++ b/llvm/test/CodeGen/AMDGPU/ctlz_zero_undef.ll @@ -322,9 +322,8 @@ define amdgpu_kernel void @s_ctlz_zero_undef_i8_with_select(ptr addrspace(1) noa ; SI-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 ; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_waitcnt lgkmcnt(0) -; SI-NEXT: s_and_b32 s2, s2, 0xff -; SI-NEXT: s_flbit_i32_b32 s2, s2 -; SI-NEXT: s_sub_i32 s4, s2, 24 +; SI-NEXT: s_lshl_b32 s2, s2, 24 +; SI-NEXT: s_flbit_i32_b32 s4, s2 ; SI-NEXT: s_mov_b32 s2, -1 ; SI-NEXT: v_mov_b32_e32 v0, s4 ; SI-NEXT: buffer_store_byte v0, off, s[0:3], 0 @@ -335,9 +334,8 @@ define amdgpu_kernel void @s_ctlz_zero_undef_i8_with_select(ptr addrspace(1) noa ; VI-NEXT: s_load_dword s2, s[0:1], 0x2c ; VI-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 ; VI-NEXT: s_waitcnt lgkmcnt(0) -; VI-NEXT: s_and_b32 s2, s2, 0xff +; VI-NEXT: s_lshl_b32 s2, s2, 24 ; VI-NEXT: s_flbit_i32_b32 s2, s2 -; VI-NEXT: s_sub_i32 s2, s2, 24 ; VI-NEXT: v_mov_b32_e32 v0, s0 ; VI-NEXT: v_mov_b32_e32 v1, s1 ; VI-NEXT: v_mov_b32_e32 v2, s2 @@ -357,13 +355,13 @@ define amdgpu_kernel void @s_ctlz_zero_undef_i8_with_select(ptr addrspace(1) noa ; EG-NEXT: ALU clause starting at 8: ; EG-NEXT: MOV * T0.X, 0.0, ; EG-NEXT: ALU clause starting at 9: -; EG-NEXT: FFBH_UINT T0.W, T0.X, +; EG-NEXT: LSHL * T0.W, T0.X, literal.x, +; EG-NEXT: 24(3.363116e-44), 0(0.000000e+00) +; EG-NEXT: FFBH_UINT T0.W, PV.W, ; EG-NEXT: AND_INT * T1.W, KC0[2].Y, literal.x, ; EG-NEXT: 3(4.203895e-45), 0(0.000000e+00) -; EG-NEXT: ADD_INT * T0.W, PV.W, literal.x, -; EG-NEXT: -24(nan), 0(0.000000e+00) ; EG-NEXT: AND_INT T0.W, PV.W, literal.x, -; EG-NEXT: LSHL * T1.W, T1.W, literal.y, +; EG-NEXT: LSHL * T1.W, PS, literal.y, ; EG-NEXT: 255(3.573311e-43), 3(4.203895e-45) ; EG-NEXT: LSHL T0.X, PV.W, PS, ; EG-NEXT: LSHL * T0.W, literal.x, PS, @@ -379,9 +377,8 @@ define amdgpu_kernel void @s_ctlz_zero_undef_i8_with_select(ptr addrspace(1) noa ; GFX9-GISEL-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x24 ; GFX9-GISEL-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-GISEL-NEXT: s_waitcnt lgkmcnt(0) -; GFX9-GISEL-NEXT: s_and_b32 s0, s4, 0xff +; GFX9-GISEL-NEXT: s_lshr_b32 s0, s4, 24 ; GFX9-GISEL-NEXT: s_flbit_i32_b32 s0, s0 -; GFX9-GISEL-NEXT: s_sub_i32 s0, s0, 24 ; GFX9-GISEL-NEXT: v_mov_b32_e32 v0, s0 ; GFX9-GISEL-NEXT: global_store_byte v1, v0, s[2:3] ; GFX9-GISEL-NEXT: s_endpgm @@ -399,9 +396,8 @@ define amdgpu_kernel void @s_ctlz_zero_undef_i16_with_select(ptr addrspace(1) no ; SI-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 ; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_waitcnt lgkmcnt(0) -; SI-NEXT: s_and_b32 s2, s2, 0xffff -; SI-NEXT: s_flbit_i32_b32 s2, s2 -; SI-NEXT: s_add_i32 s4, s2, -16 +; SI-NEXT: s_lshl_b32 s2, s2, 16 +; SI-NEXT: s_flbit_i32_b32 s4, s2 ; SI-NEXT: s_mov_b32 s2, -1 ; SI-NEXT: v_mov_b32_e32 v0, s4 ; SI-NEXT: buffer_store_short v0, off, s[0:3], 0 @@ -434,13 +430,13 @@ define amdgpu_kernel void @s_ctlz_zero_undef_i16_with_select(ptr addrspace(1) no ; EG-NEXT: ALU clause starting at 8: ; EG-NEXT: MOV * T0.X, 0.0, ; EG-NEXT: ALU clause starting at 9: -; EG-NEXT: FFBH_UINT T0.W, T0.X, +; EG-NEXT: LSHL * T0.W, T0.X, literal.x, +; EG-NEXT: 16(2.242078e-44), 0(0.000000e+00) +; EG-NEXT: FFBH_UINT T0.W, PV.W, ; EG-NEXT: AND_INT * T1.W, KC0[2].Y, literal.x, ; EG-NEXT: 3(4.203895e-45), 0(0.000000e+00) -; EG-NEXT: ADD_INT * T0.W, PV.W, literal.x, -; EG-NEXT: -16(nan), 0(0.000000e+00) ; EG-NEXT: AND_INT T0.W, PV.W, literal.x, -; EG-NEXT: LSHL * T1.W, T1.W, literal.y, +; EG-NEXT: LSHL * T1.W, PS, literal.y, ; EG-NEXT: 65535(9.183409e-41), 3(4.203895e-45) ; EG-NEXT: LSHL T0.X, PV.W, PS, ; EG-NEXT: LSHL * T0.W, literal.x, PS, @@ -456,9 +452,8 @@ define amdgpu_kernel void @s_ctlz_zero_undef_i16_with_select(ptr addrspace(1) no ; GFX9-GISEL-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x24 ; GFX9-GISEL-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-GISEL-NEXT: s_waitcnt lgkmcnt(0) -; GFX9-GISEL-NEXT: s_and_b32 s0, s4, 0xffff +; GFX9-GISEL-NEXT: s_lshr_b32 s0, s4, 16 ; GFX9-GISEL-NEXT: s_flbit_i32_b32 s0, s0 -; GFX9-GISEL-NEXT: s_sub_i32 s0, s0, 16 ; GFX9-GISEL-NEXT: v_mov_b32_e32 v0, s0 ; GFX9-GISEL-NEXT: global_store_short v1, v0, s[2:3] ; GFX9-GISEL-NEXT: s_endpgm @@ -598,8 +593,8 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i8_with_select(ptr addrspace(1) noa ; SI-NEXT: s_mov_b32 s4, s0 ; SI-NEXT: s_mov_b32 s5, s1 ; SI-NEXT: s_waitcnt vmcnt(0) -; SI-NEXT: v_ffbh_u32_e32 v1, v0 -; SI-NEXT: v_subrev_i32_e32 v1, vcc, 24, v1 +; SI-NEXT: v_lshlrev_b32_e32 v1, 24, v0 +; SI-NEXT: v_ffbh_u32_e32 v1, v1 ; SI-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0 ; SI-NEXT: v_cndmask_b32_e32 v0, 32, v1, vcc ; SI-NEXT: buffer_store_byte v0, off, s[4:7], 0 @@ -613,8 +608,8 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i8_with_select(ptr addrspace(1) noa ; VI-NEXT: v_mov_b32_e32 v1, s3 ; VI-NEXT: flat_load_ubyte v0, v[0:1] ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_ffbh_u32_sdwa v1, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 -; VI-NEXT: v_subrev_u32_e32 v1, vcc, 24, v1 +; VI-NEXT: v_lshlrev_b32_e32 v1, 24, v0 +; VI-NEXT: v_ffbh_u32_e32 v1, v1 ; VI-NEXT: v_cmp_ne_u16_e32 vcc, 0, v0 ; VI-NEXT: v_cndmask_b32_e32 v2, 32, v1, vcc ; VI-NEXT: v_mov_b32_e32 v0, s0 @@ -626,7 +621,7 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i8_with_select(ptr addrspace(1) noa ; EG: ; %bb.0: ; EG-NEXT: ALU 0, @8, KC0[CB0:0-32], KC1[] ; EG-NEXT: TEX 0 @6 -; EG-NEXT: ALU 15, @9, KC0[CB0:0-32], KC1[] +; EG-NEXT: ALU 16, @9, KC0[CB0:0-32], KC1[] ; EG-NEXT: MEM_RAT MSKOR T0.XW, T1.X ; EG-NEXT: CF_END ; EG-NEXT: PAD @@ -635,10 +630,11 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i8_with_select(ptr addrspace(1) noa ; EG-NEXT: ALU clause starting at 8: ; EG-NEXT: MOV * T0.X, KC0[2].Z, ; EG-NEXT: ALU clause starting at 9: -; EG-NEXT: FFBH_UINT * T0.W, T0.X, -; EG-NEXT: ADD_INT T0.W, PV.W, literal.x, -; EG-NEXT: AND_INT * T1.W, KC0[2].Y, literal.y, -; EG-NEXT: -24(nan), 3(4.203895e-45) +; EG-NEXT: LSHL * T0.W, T0.X, literal.x, +; EG-NEXT: 24(3.363116e-44), 0(0.000000e+00) +; EG-NEXT: FFBH_UINT T0.W, PV.W, +; EG-NEXT: AND_INT * T1.W, KC0[2].Y, literal.x, +; EG-NEXT: 3(4.203895e-45), 0(0.000000e+00) ; EG-NEXT: CNDE_INT * T0.W, T0.X, literal.x, PV.W, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) ; EG-NEXT: AND_INT T0.W, PV.W, literal.x, @@ -659,8 +655,7 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i8_with_select(ptr addrspace(1) noa ; GFX9-GISEL-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-GISEL-NEXT: global_load_ubyte v1, v0, s[2:3] ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) -; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v2, v1 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v2, 24, v2 +; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v2, v1 ; GFX9-GISEL-NEXT: v_and_b32_e32 v2, 0xff, v2 ; GFX9-GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v1 ; GFX9-GISEL-NEXT: v_cndmask_b32_e32 v1, 32, v2, vcc @@ -693,8 +688,8 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i16_with_select(ptr addrspace(1) no ; SI-NEXT: v_lshlrev_b32_e32 v0, 8, v0 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_or_b32_e32 v0, v0, v1 -; SI-NEXT: v_ffbh_u32_e32 v1, v0 -; SI-NEXT: v_add_i32_e32 v1, vcc, -16, v1 +; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v0 +; SI-NEXT: v_ffbh_u32_e32 v1, v1 ; SI-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0 ; SI-NEXT: v_cndmask_b32_e32 v0, 32, v1, vcc ; SI-NEXT: buffer_store_short v0, off, s[4:7], 0 @@ -729,7 +724,7 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i16_with_select(ptr addrspace(1) no ; EG: ; %bb.0: ; EG-NEXT: ALU 0, @8, KC0[CB0:0-32], KC1[] ; EG-NEXT: TEX 0 @6 -; EG-NEXT: ALU 15, @9, KC0[CB0:0-32], KC1[] +; EG-NEXT: ALU 16, @9, KC0[CB0:0-32], KC1[] ; EG-NEXT: MEM_RAT MSKOR T0.XW, T1.X ; EG-NEXT: CF_END ; EG-NEXT: PAD @@ -738,10 +733,11 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i16_with_select(ptr addrspace(1) no ; EG-NEXT: ALU clause starting at 8: ; EG-NEXT: MOV * T0.X, KC0[2].Z, ; EG-NEXT: ALU clause starting at 9: -; EG-NEXT: FFBH_UINT * T0.W, T0.X, -; EG-NEXT: ADD_INT T0.W, PV.W, literal.x, -; EG-NEXT: AND_INT * T1.W, KC0[2].Y, literal.y, -; EG-NEXT: -16(nan), 3(4.203895e-45) +; EG-NEXT: LSHL * T0.W, T0.X, literal.x, +; EG-NEXT: 16(2.242078e-44), 0(0.000000e+00) +; EG-NEXT: FFBH_UINT T0.W, PV.W, +; EG-NEXT: AND_INT * T1.W, KC0[2].Y, literal.x, +; EG-NEXT: 3(4.203895e-45), 0(0.000000e+00) ; EG-NEXT: CNDE_INT * T0.W, T0.X, literal.x, PV.W, ; EG-NEXT: 32(4.484155e-44), 0(0.000000e+00) ; EG-NEXT: AND_INT T0.W, PV.W, literal.x, @@ -764,8 +760,7 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i16_with_select(ptr addrspace(1) no ; GFX9-GISEL-NEXT: global_load_ubyte v2, v0, s[2:3] offset:1 ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) ; GFX9-GISEL-NEXT: v_lshl_or_b32 v1, v2, 8, v1 -; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v2, v1 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v2, 16, v2 +; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v2, v1 ; GFX9-GISEL-NEXT: v_and_b32_e32 v2, 0xffff, v2 ; GFX9-GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v1 ; GFX9-GISEL-NEXT: v_cndmask_b32_e32 v1, 32, v2, vcc @@ -1110,8 +1105,8 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i8(ptr addrspace(1) noalias %out, p ; SI-NEXT: s_mov_b32 s4, s0 ; SI-NEXT: s_mov_b32 s5, s1 ; SI-NEXT: s_waitcnt vmcnt(0) +; SI-NEXT: v_lshlrev_b32_e32 v0, 24, v0 ; SI-NEXT: v_ffbh_u32_e32 v0, v0 -; SI-NEXT: v_subrev_i32_e32 v0, vcc, 24, v0 ; SI-NEXT: buffer_store_byte v0, off, s[4:7], 0 ; SI-NEXT: s_endpgm ; @@ -1124,8 +1119,8 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i8(ptr addrspace(1) noalias %out, p ; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; VI-NEXT: flat_load_ubyte v0, v[0:1] ; VI-NEXT: s_waitcnt vmcnt(0) -; VI-NEXT: v_ffbh_u32_e32 v0, v0 -; VI-NEXT: v_subrev_u32_e32 v2, vcc, 24, v0 +; VI-NEXT: v_lshlrev_b32_e32 v0, 24, v0 +; VI-NEXT: v_ffbh_u32_e32 v2, v0 ; VI-NEXT: v_mov_b32_e32 v0, s0 ; VI-NEXT: v_mov_b32_e32 v1, s1 ; VI-NEXT: flat_store_byte v[0:1], v2 @@ -1144,13 +1139,13 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i8(ptr addrspace(1) noalias %out, p ; EG-NEXT: ALU clause starting at 8: ; EG-NEXT: ADD_INT * T0.X, KC0[2].Z, T0.X, ; EG-NEXT: ALU clause starting at 9: -; EG-NEXT: FFBH_UINT T0.W, T0.X, +; EG-NEXT: LSHL * T0.W, T0.X, literal.x, +; EG-NEXT: 24(3.363116e-44), 0(0.000000e+00) +; EG-NEXT: FFBH_UINT T0.W, PV.W, ; EG-NEXT: AND_INT * T1.W, KC0[2].Y, literal.x, ; EG-NEXT: 3(4.203895e-45), 0(0.000000e+00) -; EG-NEXT: ADD_INT * T0.W, PV.W, literal.x, -; EG-NEXT: -24(nan), 0(0.000000e+00) ; EG-NEXT: AND_INT T0.W, PV.W, literal.x, -; EG-NEXT: LSHL * T1.W, T1.W, literal.y, +; EG-NEXT: LSHL * T1.W, PS, literal.y, ; EG-NEXT: 255(3.573311e-43), 3(4.203895e-45) ; EG-NEXT: LSHL T0.X, PV.W, PS, ; EG-NEXT: LSHL * T0.W, literal.x, PS, @@ -1172,8 +1167,7 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i8(ptr addrspace(1) noalias %out, p ; GFX9-GISEL-NEXT: global_load_ubyte v0, v[0:1], off ; GFX9-GISEL-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) -; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v0, v0 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v0, 24, v0 +; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v0, v0 ; GFX9-GISEL-NEXT: global_store_byte v1, v0, s[0:1] ; GFX9-GISEL-NEXT: s_endpgm %tid = call i32 @llvm.amdgcn.workitem.id.x() @@ -1709,12 +1703,11 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i8_sel_eq_neg1(ptr addrspace(1) noa ; GFX9-GISEL-NEXT: v_add_co_u32_e32 v0, vcc, v1, v0 ; GFX9-GISEL-NEXT: v_addc_co_u32_e32 v1, vcc, v2, v3, vcc ; GFX9-GISEL-NEXT: global_load_ubyte v0, v[0:1], off -; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) -; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v1, v0 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v1, 24, v1 -; GFX9-GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 -; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v0, v1, -1, vcc ; GFX9-GISEL-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) +; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v2, v0 +; GFX9-GISEL-NEXT: v_cmp_eq_u32_sdwa s[2:3], v0, v1 +; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v0, v2, -1, s[2:3] ; GFX9-GISEL-NEXT: global_store_byte v1, v0, s[0:1] ; GFX9-GISEL-NEXT: s_endpgm %tid = call i32 @llvm.amdgcn.workitem.id.x() @@ -2193,9 +2186,8 @@ define i7 @v_ctlz_zero_undef_i7(i7 %val) { ; GFX9-GISEL-LABEL: v_ctlz_zero_undef_i7: ; GFX9-GISEL: ; %bb.0: ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0x7f, v0 +; GFX9-GISEL-NEXT: v_lshrrev_b32_e32 v0, 25, v0 ; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v0, v0 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v0, 25, v0 ; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31] %ctlz = call i7 @llvm.ctlz.i7(i7 %val, i1 true) ret i7 %ctlz @@ -2286,9 +2278,8 @@ define amdgpu_kernel void @s_ctlz_zero_undef_i18(ptr addrspace(1) noalias %out, ; GFX9-GISEL-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x24 ; GFX9-GISEL-NEXT: v_mov_b32_e32 v0, 0 ; GFX9-GISEL-NEXT: s_waitcnt lgkmcnt(0) -; GFX9-GISEL-NEXT: s_and_b32 s0, s4, 0x3ffff +; GFX9-GISEL-NEXT: s_lshr_b32 s0, s4, 14 ; GFX9-GISEL-NEXT: s_flbit_i32_b32 s0, s0 -; GFX9-GISEL-NEXT: s_sub_i32 s0, s0, 14 ; GFX9-GISEL-NEXT: s_and_b32 s0, s0, 0x3ffff ; GFX9-GISEL-NEXT: s_lshr_b32 s1, s0, 16 ; GFX9-GISEL-NEXT: v_mov_b32_e32 v1, s0 @@ -2326,9 +2317,8 @@ define i18 @v_ctlz_zero_undef_i18(i18 %val) { ; GFX9-GISEL-LABEL: v_ctlz_zero_undef_i18: ; GFX9-GISEL: ; %bb.0: ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0x3ffff, v0 +; GFX9-GISEL-NEXT: v_lshrrev_b32_e32 v0, 14, v0 ; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v0, v0 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v0, 14, v0 ; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31] %ctlz = call i18 @llvm.ctlz.i18(i18 %val, i1 true) ret i18 %ctlz @@ -2365,12 +2355,10 @@ define <2 x i18> @v_ctlz_zero_undef_v2i18(<2 x i18> %val) { ; GFX9-GISEL-LABEL: v_ctlz_zero_undef_v2i18: ; GFX9-GISEL: ; %bb.0: ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0x3ffff, v0 -; GFX9-GISEL-NEXT: v_and_b32_e32 v1, 0x3ffff, v1 +; GFX9-GISEL-NEXT: v_lshrrev_b32_e32 v0, 14, v0 +; GFX9-GISEL-NEXT: v_lshrrev_b32_e32 v1, 14, v1 ; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v0, v0 ; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v1, v1 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v0, 14, v0 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v1, 14, v1 ; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31] %ctlz = call <2 x i18> @llvm.ctlz.v2i18(<2 x i18> %val, i1 true) ret <2 x i18> %ctlz @@ -2380,16 +2368,12 @@ define <2 x i16> @v_ctlz_zero_undef_v2i16(<2 x i16> %val) { ; SI-LABEL: v_ctlz_zero_undef_v2i16: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; SI-NEXT: v_and_b32_e32 v1, 0xffff, v1 -; SI-NEXT: v_and_b32_e32 v0, 0xffff, v0 +; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 +; SI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 ; SI-NEXT: v_ffbh_u32_e32 v1, v1 -; SI-NEXT: v_ffbh_u32_e32 v0, v0 -; SI-NEXT: v_add_i32_e32 v1, vcc, -16, v1 -; SI-NEXT: v_add_i32_e32 v0, vcc, -16, v0 ; SI-NEXT: v_lshlrev_b32_e32 v2, 16, v1 -; SI-NEXT: v_and_b32_e32 v0, 0xffff, v0 +; SI-NEXT: v_ffbh_u32_e32 v0, v0 ; SI-NEXT: v_or_b32_e32 v0, v0, v2 -; SI-NEXT: v_and_b32_e32 v1, 0xffff, v1 ; SI-NEXT: s_setpc_b64 s[30:31] ; ; VI-LABEL: v_ctlz_zero_undef_v2i16: @@ -2410,12 +2394,10 @@ define <2 x i16> @v_ctlz_zero_undef_v2i16(<2 x i16> %val) { ; GFX9-GISEL-LABEL: v_ctlz_zero_undef_v2i16: ; GFX9-GISEL: ; %bb.0: ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v1, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v1, 16, v1 ; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v0, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v0, 16, v0 -; GFX9-GISEL-NEXT: v_and_b32_e32 v1, 0xffff, v1 -; GFX9-GISEL-NEXT: v_lshl_or_b32 v0, v0, 16, v1 +; GFX9-GISEL-NEXT: s_flbit_i32_b32 s4, 0 +; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0xffff, v0 +; GFX9-GISEL-NEXT: v_lshl_or_b32 v0, s4, 16, v0 ; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31] %ctlz = call <2 x i16> @llvm.ctlz.v2i16(<2 x i16> %val, i1 true) ret <2 x i16> %ctlz @@ -2425,20 +2407,15 @@ define <3 x i16> @v_ctlz_zero_undef_v3i16(<3 x i16> %val) { ; SI-LABEL: v_ctlz_zero_undef_v3i16: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; SI-NEXT: v_and_b32_e32 v1, 0xffff, v1 -; SI-NEXT: v_and_b32_e32 v0, 0xffff, v0 -; SI-NEXT: v_and_b32_e32 v2, 0xffff, v2 +; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 +; SI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; SI-NEXT: v_lshlrev_b32_e32 v2, 16, v2 ; SI-NEXT: v_ffbh_u32_e32 v1, v1 ; SI-NEXT: v_ffbh_u32_e32 v0, v0 -; SI-NEXT: v_ffbh_u32_e32 v2, v2 +; SI-NEXT: v_ffbh_u32_e32 v3, v2 ; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 -; SI-NEXT: v_add_i32_e32 v0, vcc, -16, v0 -; SI-NEXT: v_add_i32_e32 v3, vcc, -16, v2 -; SI-NEXT: v_and_b32_e32 v0, 0xffff, v0 -; SI-NEXT: v_and_b32_e32 v2, 0xffff, v3 -; SI-NEXT: v_or_b32_e32 v0, v1, v0 -; SI-NEXT: v_add_i32_e32 v0, vcc, 0xfff00000, v0 -; SI-NEXT: v_or_b32_e32 v2, 0x100000, v2 +; SI-NEXT: v_or_b32_e32 v0, v0, v1 +; SI-NEXT: v_or_b32_e32 v2, 0x200000, v3 ; SI-NEXT: v_alignbit_b32 v1, v3, v0, 16 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -2462,14 +2439,11 @@ define <3 x i16> @v_ctlz_zero_undef_v3i16(<3 x i16> %val) { ; GFX9-GISEL-LABEL: v_ctlz_zero_undef_v3i16: ; GFX9-GISEL: ; %bb.0: ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v2, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v2, 16, v2 ; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v0, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v0, 16, v0 -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v1, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 -; GFX9-GISEL-NEXT: v_and_b32_e32 v2, 0xffff, v2 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v1, 16, v1 -; GFX9-GISEL-NEXT: v_lshl_or_b32 v0, v0, 16, v2 +; GFX9-GISEL-NEXT: s_flbit_i32_b32 s4, 0 +; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0xffff, v0 +; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v1, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 +; GFX9-GISEL-NEXT: v_lshl_or_b32 v0, s4, 16, v0 ; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31] %ctlz = call <3 x i16> @llvm.ctlz.v3i16(<3 x i16> %val, i1 true) ret <3 x i16> %ctlz @@ -2479,24 +2453,18 @@ define <4 x i16> @v_ctlz_zero_undef_v4i16(<4 x i16> %val) { ; SI-LABEL: v_ctlz_zero_undef_v4i16: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; SI-NEXT: v_and_b32_e32 v3, 0xffff, v3 -; SI-NEXT: v_and_b32_e32 v2, 0xffff, v2 -; SI-NEXT: v_and_b32_e32 v1, 0xffff, v1 -; SI-NEXT: v_and_b32_e32 v0, 0xffff, v0 +; SI-NEXT: v_lshlrev_b32_e32 v3, 16, v3 +; SI-NEXT: v_lshlrev_b32_e32 v2, 16, v2 +; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 +; SI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 ; SI-NEXT: v_ffbh_u32_e32 v3, v3 ; SI-NEXT: v_ffbh_u32_e32 v2, v2 ; SI-NEXT: v_ffbh_u32_e32 v1, v1 ; SI-NEXT: v_ffbh_u32_e32 v0, v0 ; SI-NEXT: v_lshlrev_b32_e32 v3, 16, v3 -; SI-NEXT: v_add_i32_e32 v2, vcc, -16, v2 ; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 -; SI-NEXT: v_add_i32_e32 v0, vcc, -16, v0 -; SI-NEXT: v_and_b32_e32 v2, 0xffff, v2 -; SI-NEXT: v_and_b32_e32 v0, 0xffff, v0 -; SI-NEXT: v_or_b32_e32 v2, v3, v2 -; SI-NEXT: v_or_b32_e32 v0, v1, v0 -; SI-NEXT: v_add_i32_e32 v2, vcc, 0xfff00000, v2 -; SI-NEXT: v_add_i32_e32 v0, vcc, 0xfff00000, v0 +; SI-NEXT: v_or_b32_e32 v2, v2, v3 +; SI-NEXT: v_or_b32_e32 v0, v0, v1 ; SI-NEXT: v_alignbit_b32 v1, v2, v0, 16 ; SI-NEXT: v_lshrrev_b32_e32 v3, 16, v2 ; SI-NEXT: s_setpc_b64 s[30:31] @@ -2524,18 +2492,13 @@ define <4 x i16> @v_ctlz_zero_undef_v4i16(<4 x i16> %val) { ; GFX9-GISEL-LABEL: v_ctlz_zero_undef_v4i16: ; GFX9-GISEL: ; %bb.0: ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v2, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v2, 16, v2 ; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v0, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v3, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v0, 16, v0 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v3, 16, v3 ; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v1, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; GFX9-GISEL-NEXT: v_and_b32_e32 v2, 0xffff, v2 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v1, 16, v1 -; GFX9-GISEL-NEXT: v_lshl_or_b32 v0, v0, 16, v2 -; GFX9-GISEL-NEXT: v_and_b32_e32 v2, 0xffff, v3 -; GFX9-GISEL-NEXT: v_lshl_or_b32 v1, v1, 16, v2 +; GFX9-GISEL-NEXT: s_flbit_i32_b32 s4, 0 +; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0xffff, v0 +; GFX9-GISEL-NEXT: v_and_b32_e32 v1, 0xffff, v1 +; GFX9-GISEL-NEXT: v_lshl_or_b32 v0, s4, 16, v0 +; GFX9-GISEL-NEXT: v_lshl_or_b32 v1, s4, 16, v1 ; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31] %ctlz = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> %val, i1 true) ret <4 x i16> %ctlz @@ -2545,27 +2508,24 @@ define <2 x i8> @v_ctlz_zero_undef_v2i8(<2 x i8> %val) { ; SI-LABEL: v_ctlz_zero_undef_v2i8: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; SI-NEXT: v_and_b32_e32 v1, 0xff, v1 -; SI-NEXT: v_and_b32_e32 v0, 0xff, v0 +; SI-NEXT: v_lshlrev_b32_e32 v1, 24, v1 +; SI-NEXT: v_lshlrev_b32_e32 v0, 24, v0 ; SI-NEXT: v_ffbh_u32_e32 v1, v1 +; SI-NEXT: v_lshlrev_b32_e32 v2, 8, v1 ; SI-NEXT: v_ffbh_u32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v1, 8, v1 -; SI-NEXT: v_subrev_i32_e32 v0, vcc, 24, v0 -; SI-NEXT: v_and_b32_e32 v0, 0xff, v0 -; SI-NEXT: v_or_b32_e32 v0, v1, v0 -; SI-NEXT: v_add_i32_e32 v0, vcc, 0xffffe800, v0 -; SI-NEXT: v_bfe_u32 v1, v0, 8, 8 +; SI-NEXT: v_or_b32_e32 v0, v0, v2 ; SI-NEXT: s_setpc_b64 s[30:31] ; ; VI-LABEL: v_ctlz_zero_undef_v2i8: ; VI: ; %bb.0: ; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; VI-NEXT: v_ffbh_u32_sdwa v1, v1 dst_sel:BYTE_1 dst_unused:UNUSED_PAD src0_sel:BYTE_0 -; VI-NEXT: v_ffbh_u32_sdwa v0, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 -; VI-NEXT: v_add_u16_e32 v1, 0xe800, v1 -; VI-NEXT: v_subrev_u16_e32 v0, 24, v0 -; VI-NEXT: v_or_b32_sdwa v0, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; VI-NEXT: v_lshrrev_b16_e32 v1, 8, v1 +; VI-NEXT: v_lshlrev_b32_e32 v1, 24, v1 +; VI-NEXT: v_ffbh_u32_e32 v1, v1 +; VI-NEXT: v_lshlrev_b32_e32 v0, 24, v0 +; VI-NEXT: v_lshlrev_b16_e32 v2, 8, v1 +; VI-NEXT: v_ffbh_u32_e32 v0, v0 +; VI-NEXT: v_or_b32_e32 v0, v0, v2 +; VI-NEXT: v_and_b32_e32 v1, 0xff, v1 ; VI-NEXT: s_setpc_b64 s[30:31] ; ; EG-LABEL: v_ctlz_zero_undef_v2i8: @@ -2576,10 +2536,8 @@ define <2 x i8> @v_ctlz_zero_undef_v2i8(<2 x i8> %val) { ; GFX9-GISEL-LABEL: v_ctlz_zero_undef_v2i8: ; GFX9-GISEL: ; %bb.0: ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v0, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v1, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v0, 24, v0 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v1, 24, v1 +; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v0, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 +; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v1, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 ; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31] %ctlz = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %val, i1 true) ret <2 x i8> %ctlz @@ -2621,12 +2579,10 @@ define <2 x i7> @v_ctlz_zero_undef_v2i7(<2 x i7> %val) { ; GFX9-GISEL-LABEL: v_ctlz_zero_undef_v2i7: ; GFX9-GISEL: ; %bb.0: ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0x7f, v0 -; GFX9-GISEL-NEXT: v_and_b32_e32 v1, 0x7f, v1 +; GFX9-GISEL-NEXT: v_lshrrev_b32_e32 v0, 25, v0 +; GFX9-GISEL-NEXT: v_lshrrev_b32_e32 v1, 25, v1 ; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v0, v0 ; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v1, v1 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v0, 25, v0 -; GFX9-GISEL-NEXT: v_subrev_u32_e32 v1, 25, v1 ; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31] %ctlz = call <2 x i7> @llvm.ctlz.v2i7(<2 x i7> %val, i1 true) ret <2 x i7> %ctlz -- GitLab From ad625a407622ba5817ef58e30357139a40cf929e Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 19 May 2024 14:51:13 -0700 Subject: [PATCH 037/793] [TableGen] Avoid std::string copy. NFC Fix #92702 --- llvm/utils/TableGen/ARMTargetDefEmitter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/utils/TableGen/ARMTargetDefEmitter.cpp b/llvm/utils/TableGen/ARMTargetDefEmitter.cpp index 491011643bbf..b79458529623 100644 --- a/llvm/utils/TableGen/ARMTargetDefEmitter.cpp +++ b/llvm/utils/TableGen/ARMTargetDefEmitter.cpp @@ -170,7 +170,7 @@ static void EmitARMTargetDef(RecordKeeper &RK, raw_ostream &OS) { << "/// The set of all architectures\n" << "static constexpr std::array ArchInfos = {\n"; - for (auto CppSpelling : CppSpellings) + for (StringRef CppSpelling : CppSpellings) OS << " &" << CppSpelling << ",\n"; OS << "};\n"; -- GitLab From 7892d434741ba0ac755e00ae96ca7cdcfaf82d35 Mon Sep 17 00:00:00 2001 From: Ryuichi Watanabe Date: Mon, 20 May 2024 07:01:47 +0900 Subject: [PATCH 038/793] Update llvm-bugs.yml (#77243) --- .github/workflows/llvm-bugs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/llvm-bugs.yml b/.github/workflows/llvm-bugs.yml index f592dd6ccd90..c392078fa452 100644 --- a/.github/workflows/llvm-bugs.yml +++ b/.github/workflows/llvm-bugs.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'llvm/llvm-project' steps: - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18 check-latest: true -- GitLab From b603237b6c067e82a7c6b73adb7e18c8edfb40dd Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Sun, 19 May 2024 15:02:44 -0700 Subject: [PATCH 039/793] [llvm] Use operator==(StringRef, StringRef) (NFC) (#92705) --- llvm/lib/Option/OptTable.cpp | 2 +- llvm/lib/ProfileData/InstrProfCorrelator.cpp | 10 ++++------ llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp | 6 +++--- llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 2 +- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Option/OptTable.cpp b/llvm/lib/Option/OptTable.cpp index b8b6b90c253f..3eceb0fbdfc4 100644 --- a/llvm/lib/Option/OptTable.cpp +++ b/llvm/lib/Option/OptTable.cpp @@ -197,7 +197,7 @@ OptTable::suggestValueCompletions(StringRef Option, StringRef Arg) const { std::vector Result; for (StringRef Val : Candidates) - if (Val.starts_with(Arg) && Arg.compare(Val)) + if (Val.starts_with(Arg) && Arg != Val) Result.push_back(std::string(Val)); return Result; } diff --git a/llvm/lib/ProfileData/InstrProfCorrelator.cpp b/llvm/lib/ProfileData/InstrProfCorrelator.cpp index cf80a58f43bd..44e2aeb00d8c 100644 --- a/llvm/lib/ProfileData/InstrProfCorrelator.cpp +++ b/llvm/lib/ProfileData/InstrProfCorrelator.cpp @@ -350,16 +350,14 @@ void DwarfInstrProfCorrelator::correlateProfileDataImpl( continue; } StringRef AnnotationName = *AnnotationNameOrErr; - if (AnnotationName.compare( - InstrProfCorrelator::FunctionNameAttributeName) == 0) { + if (AnnotationName == InstrProfCorrelator::FunctionNameAttributeName) { if (auto EC = AnnotationFormValue->getAsCString().moveInto(FunctionName)) consumeError(std::move(EC)); - } else if (AnnotationName.compare( - InstrProfCorrelator::CFGHashAttributeName) == 0) { + } else if (AnnotationName == InstrProfCorrelator::CFGHashAttributeName) { CFGHash = AnnotationFormValue->getAsUnsignedConstant(); - } else if (AnnotationName.compare( - InstrProfCorrelator::NumCountersAttributeName) == 0) { + } else if (AnnotationName == + InstrProfCorrelator::NumCountersAttributeName) { NumCounters = AnnotationFormValue->getAsUnsignedConstant(); } } diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp index 727e4e584c05..f4daab7d06eb 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp @@ -171,9 +171,9 @@ getArgAccessQual(const Function &F, unsigned ArgIdx) { if (!ArgAttribute) return SPIRV::AccessQualifier::ReadWrite; - if (ArgAttribute->getString().compare("read_only") == 0) + if (ArgAttribute->getString() == "read_only") return SPIRV::AccessQualifier::ReadOnly; - if (ArgAttribute->getString().compare("write_only") == 0) + if (ArgAttribute->getString() == "write_only") return SPIRV::AccessQualifier::WriteOnly; return SPIRV::AccessQualifier::ReadWrite; } @@ -181,7 +181,7 @@ getArgAccessQual(const Function &F, unsigned ArgIdx) { static std::vector getKernelArgTypeQual(const Function &F, unsigned ArgIdx) { MDString *ArgAttribute = getOCLKernelArgTypeQual(F, ArgIdx); - if (ArgAttribute && ArgAttribute->getString().compare("volatile") == 0) + if (ArgAttribute && ArgAttribute->getString() == "volatile") return {SPIRV::Decoration::Volatile}; return {}; } diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index 62b4a9278954..662310610931 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -1802,7 +1802,7 @@ bool X86AsmParser::ParseIntelNamedOperator(StringRef Name, bool &ParseError, SMLoc &End) { // A named operator should be either lower or upper case, but not a mix... // except in MASM, which uses full case-insensitivity. - if (Name.compare(Name.lower()) && Name.compare(Name.upper()) && + if (Name != Name.lower() && Name != Name.upper() && !getParser().isParsingMasm()) return false; if (Name.equals_insensitive("not")) { -- GitLab From 2d5e488c98225108aebfe4aa4acfe6ec1f234a37 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sun, 19 May 2024 15:09:03 -0700 Subject: [PATCH 040/793] [clang-format][NFC] Clean up SortIncludesTest.cpp Wherever applicable, replace EXPECT_EQ with verifyFormat and std::string with StringRef. Also, change a raw string literal to a regular one. --- clang/unittests/Format/SortIncludesTest.cpp | 1942 +++++++++---------- 1 file changed, 970 insertions(+), 972 deletions(-) diff --git a/clang/unittests/Format/SortIncludesTest.cpp b/clang/unittests/Format/SortIncludesTest.cpp index 824fa0078cd0..52ba19627182 100644 --- a/clang/unittests/Format/SortIncludesTest.cpp +++ b/clang/unittests/Format/SortIncludesTest.cpp @@ -53,35 +53,35 @@ protected: }; TEST_F(SortIncludesTest, BasicSorting) { - EXPECT_EQ("#include \"a.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"", - sort("#include \"a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\"")); - - EXPECT_EQ("// comment\n" - "#include \n" - "#include ", - sort("// comment\n" - "#include \n" - "#include ", - {tooling::Range(25, 1)})); + verifyFormat("#include \"a.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"", + sort("#include \"a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\"")); + + verifyFormat("// comment\n" + "#include \n" + "#include ", + sort("// comment\n" + "#include \n" + "#include ", + {tooling::Range(25, 1)})); } TEST_F(SortIncludesTest, TrailingComments) { - EXPECT_EQ("#include \"a.h\"\n" - "#include \"b.h\" /* long\n" - " * long\n" - " * comment*/\n" - "#include \"c.h\"\n" - "#include \"d.h\"", - sort("#include \"a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\" /* long\n" - " * long\n" - " * comment*/\n" - "#include \"d.h\"")); + verifyFormat("#include \"a.h\"\n" + "#include \"b.h\" /* long\n" + " * long\n" + " * comment*/\n" + "#include \"c.h\"\n" + "#include \"d.h\"", + sort("#include \"a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\" /* long\n" + " * long\n" + " * comment*/\n" + "#include \"d.h\"")); } TEST_F(SortIncludesTest, SortedIncludesUsingSortPriorityAttribute) { @@ -100,531 +100,531 @@ TEST_F(SortIncludesTest, SortedIncludesUsingSortPriorityAttribute) { {"", 8, 10, false}, {"^\".*\\.h\"", 10, 12, false}}; - EXPECT_EQ("#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "\n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "\n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "\n" - "#include \n" - "\n" - "#include \"pathnames.h\"", - sort("#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \"pathnames.h\"\n" - "#include \n" - "#include \n" - "#include \n" - "#include ")); + verifyFormat("#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "\n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "\n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "\n" + "#include \n" + "\n" + "#include \"pathnames.h\"", + sort("#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \"pathnames.h\"\n" + "#include \n" + "#include \n" + "#include \n" + "#include ")); } TEST_F(SortIncludesTest, SortPriorityNotDefined) { FmtStyle = getLLVMStyle(); - EXPECT_EQ("#include \"FormatTestUtils.h\"\n" - "#include \"clang/Format/Format.h\"\n" - "#include \"llvm/ADT/None.h\"\n" - "#include \"llvm/Support/Debug.h\"\n" - "#include \"gtest/gtest.h\"", - sort("#include \"clang/Format/Format.h\"\n" - "#include \"llvm/ADT/None.h\"\n" - "#include \"FormatTestUtils.h\"\n" - "#include \"gtest/gtest.h\"\n" - "#include \"llvm/Support/Debug.h\"")); + verifyFormat("#include \"FormatTestUtils.h\"\n" + "#include \"clang/Format/Format.h\"\n" + "#include \"llvm/ADT/None.h\"\n" + "#include \"llvm/Support/Debug.h\"\n" + "#include \"gtest/gtest.h\"", + sort("#include \"clang/Format/Format.h\"\n" + "#include \"llvm/ADT/None.h\"\n" + "#include \"FormatTestUtils.h\"\n" + "#include \"gtest/gtest.h\"\n" + "#include \"llvm/Support/Debug.h\"")); } TEST_F(SortIncludesTest, NoReplacementsForValidIncludes) { // Identical #includes have led to a failure with an unstable sort. - std::string Code = "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n"; + StringRef Code = "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n"; EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a.cc").empty()); } TEST_F(SortIncludesTest, MainFileHeader) { - std::string Code = "#include \n" - "\n" - "#include \"a/extra_action.proto.h\"\n"; + StringRef Code = "#include \n" + "\n" + "#include \"a/extra_action.proto.h\"\n"; FmtStyle = getGoogleStyle(FormatStyle::LK_Cpp); EXPECT_TRUE( sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a/extra_action.cc") .empty()); - EXPECT_EQ("#include \"foo.bar.h\"\n" - "\n" - "#include \"a.h\"", - sort("#include \"a.h\"\n" - "#include \"foo.bar.h\"", - "foo.bar.cc")); + verifyFormat("#include \"foo.bar.h\"\n" + "\n" + "#include \"a.h\"", + sort("#include \"a.h\"\n" + "#include \"foo.bar.h\"", + "foo.bar.cc")); } TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) { Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; - EXPECT_EQ("#include \"a.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"", - sort("#include \"a.h\"\n" - "#include \"c.h\"\n" - "\n" - "\n" - "#include \"b.h\"")); + verifyFormat("#include \"a.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"", + sort("#include \"a.h\"\n" + "#include \"c.h\"\n" + "\n" + "\n" + "#include \"b.h\"")); Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; - EXPECT_EQ("#include \"a.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"", - sort("#include \"a.h\"\n" - "#include \"c.h\"\n" - "\n" - "\n" - "#include \"b.h\"")); + verifyFormat("#include \"a.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"", + sort("#include \"a.h\"\n" + "#include \"c.h\"\n" + "\n" + "\n" + "#include \"b.h\"")); } TEST_F(SortIncludesTest, SupportClangFormatOff) { - EXPECT_EQ("#include \n" - "#include \n" - "#include \n" - "// clang-format off\n" - "#include \n" - "#include \n" - "#include \n" - "// clang-format on", - sort("#include \n" - "#include \n" - "#include \n" - "// clang-format off\n" - "#include \n" - "#include \n" - "#include \n" - "// clang-format on")); + verifyFormat("#include \n" + "#include \n" + "#include \n" + "// clang-format off\n" + "#include \n" + "#include \n" + "#include \n" + "// clang-format on", + sort("#include \n" + "#include \n" + "#include \n" + "// clang-format off\n" + "#include \n" + "#include \n" + "#include \n" + "// clang-format on")); Style.IncludeBlocks = Style.IBS_Merge; - std::string Code = "// clang-format off\r\n" - "#include \"d.h\"\r\n" - "#include \"b.h\"\r\n" - "// clang-format on\r\n" - "\r\n" - "#include \"c.h\"\r\n" - "#include \"a.h\"\r\n" - "#include \"e.h\"\r\n"; - - std::string Expected = "// clang-format off\r\n" - "#include \"d.h\"\r\n" - "#include \"b.h\"\r\n" - "// clang-format on\r\n" - "\r\n" - "#include \"e.h\"\r\n" - "#include \"a.h\"\r\n" - "#include \"c.h\"\r\n"; - - EXPECT_EQ(Expected, sort(Code, "e.cpp", 1)); + StringRef Code = "// clang-format off\r\n" + "#include \"d.h\"\r\n" + "#include \"b.h\"\r\n" + "// clang-format on\r\n" + "\r\n" + "#include \"c.h\"\r\n" + "#include \"a.h\"\r\n" + "#include \"e.h\"\r\n"; + + StringRef Expected = "// clang-format off\r\n" + "#include \"d.h\"\r\n" + "#include \"b.h\"\r\n" + "// clang-format on\r\n" + "\r\n" + "#include \"e.h\"\r\n" + "#include \"a.h\"\r\n" + "#include \"c.h\"\r\n"; + + verifyFormat(Expected, sort(Code, "e.cpp", 1)); } TEST_F(SortIncludesTest, SupportClangFormatOffCStyle) { - EXPECT_EQ("#include \n" - "#include \n" - "#include \n" - "/* clang-format off */\n" - "#include \n" - "#include \n" - "#include \n" - "/* clang-format on */", - sort("#include \n" - "#include \n" - "#include \n" - "/* clang-format off */\n" - "#include \n" - "#include \n" - "#include \n" - "/* clang-format on */")); + verifyFormat("#include \n" + "#include \n" + "#include \n" + "/* clang-format off */\n" + "#include \n" + "#include \n" + "#include \n" + "/* clang-format on */", + sort("#include \n" + "#include \n" + "#include \n" + "/* clang-format off */\n" + "#include \n" + "#include \n" + "#include \n" + "/* clang-format on */")); // Not really turning it off - EXPECT_EQ("#include \n" - "#include \n" - "#include \n" - "/* clang-format offically */\n" - "#include \n" - "#include \n" - "#include \n" - "/* clang-format onwards */", - sort("#include \n" - "#include \n" - "#include \n" - "/* clang-format offically */\n" - "#include \n" - "#include \n" - "#include \n" - "/* clang-format onwards */", - "input.h", 2)); + verifyFormat("#include \n" + "#include \n" + "#include \n" + "/* clang-format offically */\n" + "#include \n" + "#include \n" + "#include \n" + "/* clang-format onwards */", + sort("#include \n" + "#include \n" + "#include \n" + "/* clang-format offically */\n" + "#include \n" + "#include \n" + "#include \n" + "/* clang-format onwards */", + "input.h", 2)); } TEST_F(SortIncludesTest, IncludeSortingCanBeDisabled) { FmtStyle.SortIncludes = FormatStyle::SI_Never; - EXPECT_EQ("#include \"a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\"", - sort("#include \"a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\"", - "input.h", 0)); + verifyFormat("#include \"a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\"", + sort("#include \"a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\"", + "input.h", 0)); } TEST_F(SortIncludesTest, MixIncludeAndImport) { - EXPECT_EQ("#include \"a.h\"\n" - "#import \"b.h\"\n" - "#include \"c.h\"", - sort("#include \"a.h\"\n" - "#include \"c.h\"\n" - "#import \"b.h\"")); + verifyFormat("#include \"a.h\"\n" + "#import \"b.h\"\n" + "#include \"c.h\"", + sort("#include \"a.h\"\n" + "#include \"c.h\"\n" + "#import \"b.h\"")); } TEST_F(SortIncludesTest, FixTrailingComments) { - EXPECT_EQ("#include \"a.h\" // comment\n" - "#include \"bb.h\" // comment\n" - "#include \"ccc.h\"", - sort("#include \"a.h\" // comment\n" - "#include \"ccc.h\"\n" - "#include \"bb.h\" // comment")); + verifyFormat("#include \"a.h\" // comment\n" + "#include \"bb.h\" // comment\n" + "#include \"ccc.h\"", + sort("#include \"a.h\" // comment\n" + "#include \"ccc.h\"\n" + "#include \"bb.h\" // comment")); } TEST_F(SortIncludesTest, LeadingWhitespace) { - EXPECT_EQ("#include \"a.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"", - sort(" #include \"a.h\"\n" - " #include \"c.h\"\n" - " #include \"b.h\"")); - EXPECT_EQ("#include \"a.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"", - sort("# include \"a.h\"\n" - "# include \"c.h\"\n" - "# include \"b.h\"")); - EXPECT_EQ("#include \"a.h\"", sort("#include \"a.h\"\n" - " #include \"a.h\"")); + verifyFormat("#include \"a.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"", + sort(" #include \"a.h\"\n" + " #include \"c.h\"\n" + " #include \"b.h\"")); + verifyFormat("#include \"a.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"", + sort("# include \"a.h\"\n" + "# include \"c.h\"\n" + "# include \"b.h\"")); + verifyFormat("#include \"a.h\"", sort("#include \"a.h\"\n" + " #include \"a.h\"")); } TEST_F(SortIncludesTest, TrailingWhitespace) { - EXPECT_EQ("#include \"a.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"", - sort("#include \"a.h\" \n" - "#include \"c.h\" \n" - "#include \"b.h\" ")); - EXPECT_EQ("#include \"a.h\"", sort("#include \"a.h\"\n" - "#include \"a.h\" ")); + verifyFormat("#include \"a.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"", + sort("#include \"a.h\" \n" + "#include \"c.h\" \n" + "#include \"b.h\" ")); + verifyFormat("#include \"a.h\"", sort("#include \"a.h\"\n" + "#include \"a.h\" ")); } TEST_F(SortIncludesTest, GreaterInComment) { - EXPECT_EQ("#include \"a.h\"\n" - "#include \"b.h\" // >\n" - "#include \"c.h\"", - sort("#include \"a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\" // >")); + verifyFormat("#include \"a.h\"\n" + "#include \"b.h\" // >\n" + "#include \"c.h\"", + sort("#include \"a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\" // >")); } TEST_F(SortIncludesTest, SortsLocallyInEachBlock) { - EXPECT_EQ("#include \"a.h\"\n" - "#include \"c.h\"\n" - "\n" - "#include \"b.h\"", - sort("#include \"a.h\"\n" - "#include \"c.h\"\n" - "\n" - "#include \"b.h\"", - "input.h", 0)); + verifyFormat("#include \"a.h\"\n" + "#include \"c.h\"\n" + "\n" + "#include \"b.h\"", + sort("#include \"a.h\"\n" + "#include \"c.h\"\n" + "\n" + "#include \"b.h\"", + "input.h", 0)); } TEST_F(SortIncludesTest, SortsAllBlocksWhenMerging) { Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; - EXPECT_EQ("#include \"a.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"", - sort("#include \"a.h\"\n" - "#include \"c.h\"\n" - "\n" - "#include \"b.h\"")); + verifyFormat("#include \"a.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"", + sort("#include \"a.h\"\n" + "#include \"c.h\"\n" + "\n" + "#include \"b.h\"")); } TEST_F(SortIncludesTest, CommentsAlwaysSeparateGroups) { - EXPECT_EQ("#include \"a.h\"\n" - "#include \"c.h\"\n" - "// comment\n" - "#include \"b.h\"", - sort("#include \"c.h\"\n" - "#include \"a.h\"\n" - "// comment\n" - "#include \"b.h\"")); + verifyFormat("#include \"a.h\"\n" + "#include \"c.h\"\n" + "// comment\n" + "#include \"b.h\"", + sort("#include \"c.h\"\n" + "#include \"a.h\"\n" + "// comment\n" + "#include \"b.h\"")); Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; - EXPECT_EQ("#include \"a.h\"\n" - "#include \"c.h\"\n" - "// comment\n" - "#include \"b.h\"", - sort("#include \"c.h\"\n" - "#include \"a.h\"\n" - "// comment\n" - "#include \"b.h\"")); + verifyFormat("#include \"a.h\"\n" + "#include \"c.h\"\n" + "// comment\n" + "#include \"b.h\"", + sort("#include \"c.h\"\n" + "#include \"a.h\"\n" + "// comment\n" + "#include \"b.h\"")); Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; - EXPECT_EQ("#include \"a.h\"\n" - "#include \"c.h\"\n" - "// comment\n" - "#include \"b.h\"", - sort("#include \"c.h\"\n" - "#include \"a.h\"\n" - "// comment\n" - "#include \"b.h\"")); + verifyFormat("#include \"a.h\"\n" + "#include \"c.h\"\n" + "// comment\n" + "#include \"b.h\"", + sort("#include \"c.h\"\n" + "#include \"a.h\"\n" + "// comment\n" + "#include \"b.h\"")); } TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) { - EXPECT_EQ("#include \"a.h\"\n" - "#include \"c.h\"\n" - "#include \n" - "#include \n" - "#include \n" - "#include ", - sort("#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \"c.h\"\n" - "#include \"a.h\"")); + verifyFormat("#include \"a.h\"\n" + "#include \"c.h\"\n" + "#include \n" + "#include \n" + "#include \n" + "#include ", + sort("#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \"c.h\"\n" + "#include \"a.h\"")); FmtStyle = getGoogleStyle(FormatStyle::LK_Cpp); - EXPECT_EQ("#include \n" - "#include \n" - "\n" - "#include \n" - "#include \n" - "\n" - "#include \"a.h\"\n" - "#include \"c.h\"", - sort("#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \"c.h\"\n" - "#include \"a.h\"")); + verifyFormat("#include \n" + "#include \n" + "\n" + "#include \n" + "#include \n" + "\n" + "#include \"a.h\"\n" + "#include \"c.h\"", + sort("#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \"c.h\"\n" + "#include \"a.h\"")); } TEST_F(SortIncludesTest, RegroupsAngledIncludesInSeparateBlocks) { Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; - EXPECT_EQ("#include \"a.h\"\n" - "#include \"c.h\"\n" - "\n" - "#include \n" - "#include ", - sort("#include \n" - "#include \n" - "#include \"c.h\"\n" - "#include \"a.h\"")); + verifyFormat("#include \"a.h\"\n" + "#include \"c.h\"\n" + "\n" + "#include \n" + "#include ", + sort("#include \n" + "#include \n" + "#include \"c.h\"\n" + "#include \"a.h\"")); } TEST_F(SortIncludesTest, HandlesMultilineIncludes) { - EXPECT_EQ("#include \"a.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"", - sort("#include \"a.h\"\n" - "#include \\\n" - "\"c.h\"\n" - "#include \"b.h\"")); + verifyFormat("#include \"a.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"", + sort("#include \"a.h\"\n" + "#include \\\n" + "\"c.h\"\n" + "#include \"b.h\"")); } TEST_F(SortIncludesTest, HandlesTrailingCommentsWithAngleBrackets) { // Regression test from the discussion at https://reviews.llvm.org/D121370. - EXPECT_EQ("#include \n" - "\n" - "#include \"util/bar.h\"\n" - "#include \"util/foo/foo.h\" // foo", - sort("#include \n" - "\n" - "#include \"util/bar.h\"\n" - "#include \"util/foo/foo.h\" // foo", - /*FileName=*/"input.cc", - /*ExpectedNumRanges=*/0)); + verifyFormat("#include \n" + "\n" + "#include \"util/bar.h\"\n" + "#include \"util/foo/foo.h\" // foo", + sort("#include \n" + "\n" + "#include \"util/bar.h\"\n" + "#include \"util/foo/foo.h\" // foo", + /*FileName=*/"input.cc", + /*ExpectedNumRanges=*/0)); } TEST_F(SortIncludesTest, LeavesMainHeaderFirst) { Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; - EXPECT_EQ("#include \"llvm/a.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"", - sort("#include \"llvm/a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\"", - "a.cc")); - EXPECT_EQ("#include \"llvm/a.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"", - sort("#include \"llvm/a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\"", - "a_test.cc")); - EXPECT_EQ("#include \"llvm/input.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"", - sort("#include \"llvm/input.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\"", - "input.mm")); + verifyFormat("#include \"llvm/a.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"", + sort("#include \"llvm/a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\"", + "a.cc")); + verifyFormat("#include \"llvm/a.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"", + sort("#include \"llvm/a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\"", + "a_test.cc")); + verifyFormat("#include \"llvm/input.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"", + sort("#include \"llvm/input.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\"", + "input.mm")); // Don't allow prefixes. - EXPECT_EQ("#include \"b.h\"\n" - "#include \"c.h\"\n" - "#include \"llvm/not_a.h\"", - sort("#include \"llvm/not_a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\"", - "a.cc")); + verifyFormat("#include \"b.h\"\n" + "#include \"c.h\"\n" + "#include \"llvm/not_a.h\"", + sort("#include \"llvm/not_a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\"", + "a.cc")); // Don't do this for _main and other suffixes. - EXPECT_EQ("#include \"b.h\"\n" - "#include \"c.h\"\n" - "#include \"llvm/a.h\"", - sort("#include \"llvm/a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\"", - "a_main.cc")); + verifyFormat("#include \"b.h\"\n" + "#include \"c.h\"\n" + "#include \"llvm/a.h\"", + sort("#include \"llvm/a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\"", + "a_main.cc")); // Don't do this in headers. - EXPECT_EQ("#include \"b.h\"\n" - "#include \"c.h\"\n" - "#include \"llvm/a.h\"", - sort("#include \"llvm/a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\"", - "a.h")); + verifyFormat("#include \"b.h\"\n" + "#include \"c.h\"\n" + "#include \"llvm/a.h\"", + sort("#include \"llvm/a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\"", + "a.h")); // Only do this in the first #include block. - EXPECT_EQ("#include \n" - "\n" - "#include \"b.h\"\n" - "#include \"c.h\"\n" - "#include \"llvm/a.h\"", - sort("#include \n" - "\n" - "#include \"llvm/a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\"", - "a.cc")); + verifyFormat("#include \n" + "\n" + "#include \"b.h\"\n" + "#include \"c.h\"\n" + "#include \"llvm/a.h\"", + sort("#include \n" + "\n" + "#include \"llvm/a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\"", + "a.cc")); // Only recognize the first #include with a matching basename as main include. - EXPECT_EQ("#include \"a.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"\n" - "#include \"llvm/a.h\"", - sort("#include \"b.h\"\n" - "#include \"a.h\"\n" - "#include \"c.h\"\n" - "#include \"llvm/a.h\"", - "a.cc")); + verifyFormat("#include \"a.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"\n" + "#include \"llvm/a.h\"", + sort("#include \"b.h\"\n" + "#include \"a.h\"\n" + "#include \"c.h\"\n" + "#include \"llvm/a.h\"", + "a.cc")); } TEST_F(SortIncludesTest, LeavesMainHeaderFirstInAdditionalExtensions) { Style.IncludeIsMainRegex = "([-_](test|unittest))?|(Impl)?$"; - EXPECT_EQ("#include \"b.h\"\n" - "#include \"c.h\"\n" - "#include \"llvm/a.h\"", - sort("#include \"llvm/a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\"", - "a_test.xxx")); - EXPECT_EQ("#include \"b.h\"\n" - "#include \"c.h\"\n" - "#include \"llvm/a.h\"", - sort("#include \"llvm/a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\"", - "aImpl.hpp")); + verifyFormat("#include \"b.h\"\n" + "#include \"c.h\"\n" + "#include \"llvm/a.h\"", + sort("#include \"llvm/a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\"", + "a_test.xxx")); + verifyFormat("#include \"b.h\"\n" + "#include \"c.h\"\n" + "#include \"llvm/a.h\"", + sort("#include \"llvm/a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\"", + "aImpl.hpp")); // .cpp extension is considered "main" by default - EXPECT_EQ("#include \"llvm/a.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"", - sort("#include \"llvm/a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\"", - "aImpl.cpp")); - EXPECT_EQ("#include \"llvm/a.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"", - sort("#include \"llvm/a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\"", - "a_test.cpp")); + verifyFormat("#include \"llvm/a.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"", + sort("#include \"llvm/a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\"", + "aImpl.cpp")); + verifyFormat("#include \"llvm/a.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"", + sort("#include \"llvm/a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\"", + "a_test.cpp")); // Allow additional filenames / extensions Style.IncludeIsMainSourceRegex = "(Impl\\.hpp)|(\\.xxx)$"; - EXPECT_EQ("#include \"llvm/a.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"", - sort("#include \"llvm/a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\"", - "a_test.xxx")); - EXPECT_EQ("#include \"llvm/a.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"", - sort("#include \"llvm/a.h\"\n" - "#include \"c.h\"\n" - "#include \"b.h\"", - "aImpl.hpp")); + verifyFormat("#include \"llvm/a.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"", + sort("#include \"llvm/a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\"", + "a_test.xxx")); + verifyFormat("#include \"llvm/a.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"", + sort("#include \"llvm/a.h\"\n" + "#include \"c.h\"\n" + "#include \"b.h\"", + "aImpl.hpp")); } TEST_F(SortIncludesTest, RecognizeMainHeaderInAllGroups) { Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; - EXPECT_EQ("#include \"c.h\"\n" - "#include \"a.h\"\n" - "#include \"b.h\"", - sort("#include \"b.h\"\n" - "\n" - "#include \"a.h\"\n" - "#include \"c.h\"", - "c.cc")); + verifyFormat("#include \"c.h\"\n" + "#include \"a.h\"\n" + "#include \"b.h\"", + sort("#include \"b.h\"\n" + "\n" + "#include \"a.h\"\n" + "#include \"c.h\"", + "c.cc")); } TEST_F(SortIncludesTest, MainHeaderIsSeparatedWhenRegroupping) { Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; - EXPECT_EQ("#include \"a.h\"\n" - "\n" - "#include \"b.h\"\n" - "#include \"c.h\"", - sort("#include \"b.h\"\n" - "\n" - "#include \"a.h\"\n" - "#include \"c.h\"", - "a.cc")); + verifyFormat("#include \"a.h\"\n" + "\n" + "#include \"b.h\"\n" + "#include \"c.h\"", + sort("#include \"b.h\"\n" + "\n" + "#include \"a.h\"\n" + "#include \"c.h\"", + "a.cc")); } TEST_F(SortIncludesTest, SupportOptionalCaseSensitiveSorting) { @@ -632,17 +632,17 @@ TEST_F(SortIncludesTest, SupportOptionalCaseSensitiveSorting) { FmtStyle.SortIncludes = FormatStyle::SI_CaseInsensitive; - EXPECT_EQ("#include \"A/B.h\"\n" - "#include \"A/b.h\"\n" - "#include \"a/b.h\"\n" - "#include \"B/A.h\"\n" - "#include \"B/a.h\"", - sort("#include \"B/a.h\"\n" - "#include \"B/A.h\"\n" - "#include \"A/B.h\"\n" - "#include \"a/b.h\"\n" - "#include \"A/b.h\"", - "a.h")); + verifyFormat("#include \"A/B.h\"\n" + "#include \"A/b.h\"\n" + "#include \"a/b.h\"\n" + "#include \"B/A.h\"\n" + "#include \"B/a.h\"", + sort("#include \"B/a.h\"\n" + "#include \"B/A.h\"\n" + "#include \"A/B.h\"\n" + "#include \"a/b.h\"\n" + "#include \"A/b.h\"", + "a.h")); Style.IncludeBlocks = clang::tooling::IncludeStyle::IBS_Regroup; Style.IncludeCategories = { @@ -657,17 +657,17 @@ TEST_F(SortIncludesTest, SupportOptionalCaseSensitiveSorting) { "#include \"Vlib.h\"\n" "#include \"AST.h\""; - EXPECT_EQ("#include \"AST.h\"\n" - "#include \"qt.h\"\n" - "#include \"Vlib.h\"\n" - "#include \"vlib.h\"\n" - "\n" - "#include \n" - "#include \n" - "\n" - "#include \n" - "#include ", - sort(UnsortedCode)); + verifyFormat("#include \"AST.h\"\n" + "#include \"qt.h\"\n" + "#include \"Vlib.h\"\n" + "#include \"vlib.h\"\n" + "\n" + "#include \n" + "#include \n" + "\n" + "#include \n" + "#include ", + sort(UnsortedCode)); } TEST_F(SortIncludesTest, SupportCaseInsensitiveMatching) { @@ -676,21 +676,21 @@ TEST_F(SortIncludesTest, SupportCaseInsensitiveMatching) { // Ensure both main header detection and grouping work in a case insensitive // manner. - EXPECT_EQ("#include \"llvm/A.h\"\n" - "#include \"b.h\"\n" - "#include \"c.h\"\n" - "#include \"LLVM/z.h\"\n" - "#include \"llvm/X.h\"\n" - "#include \"GTest/GTest.h\"\n" - "#include \"gmock/gmock.h\"", - sort("#include \"c.h\"\n" - "#include \"b.h\"\n" - "#include \"GTest/GTest.h\"\n" - "#include \"llvm/A.h\"\n" - "#include \"gmock/gmock.h\"\n" - "#include \"llvm/X.h\"\n" - "#include \"LLVM/z.h\"", - "a_TEST.cc")); + verifyFormat("#include \"llvm/A.h\"\n" + "#include \"b.h\"\n" + "#include \"c.h\"\n" + "#include \"LLVM/z.h\"\n" + "#include \"llvm/X.h\"\n" + "#include \"GTest/GTest.h\"\n" + "#include \"gmock/gmock.h\"", + sort("#include \"c.h\"\n" + "#include \"b.h\"\n" + "#include \"GTest/GTest.h\"\n" + "#include \"llvm/A.h\"\n" + "#include \"gmock/gmock.h\"\n" + "#include \"llvm/X.h\"\n" + "#include \"LLVM/z.h\"", + "a_TEST.cc")); } TEST_F(SortIncludesTest, SupportOptionalCaseSensitiveMachting) { @@ -711,57 +711,57 @@ TEST_F(SortIncludesTest, SupportOptionalCaseSensitiveMachting) { "#include \n" "#include "; - EXPECT_EQ("#include \"qa.h\"\n" - "#include \"qt.h\"\n" - "\n" - "#include \n" - "#include \n" - "\n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "\n" - "#include ", - sort(UnsortedCode)); + verifyFormat("#include \"qa.h\"\n" + "#include \"qt.h\"\n" + "\n" + "#include \n" + "#include \n" + "\n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "\n" + "#include ", + sort(UnsortedCode)); Style.IncludeCategories[2].RegexIsCaseSensitive = true; Style.IncludeCategories[3].RegexIsCaseSensitive = true; - EXPECT_EQ("#include \"qa.h\"\n" - "#include \"qt.h\"\n" - "\n" - "#include \n" - "#include \n" - "\n" - "#include \n" - "#include \n" - "\n" - "#include \n" - "\n" - "#include \n" - "#include ", - sort(UnsortedCode)); + verifyFormat("#include \"qa.h\"\n" + "#include \"qt.h\"\n" + "\n" + "#include \n" + "#include \n" + "\n" + "#include \n" + "#include \n" + "\n" + "#include \n" + "\n" + "#include \n" + "#include ", + sort(UnsortedCode)); } TEST_F(SortIncludesTest, NegativePriorities) { Style.IncludeCategories = {{".*important_os_header.*", -1, 0, false}, {".*", 1, 0, false}}; - EXPECT_EQ("#include \"important_os_header.h\"\n" - "#include \"c_main.h\"\n" - "#include \"a_other.h\"", - sort("#include \"c_main.h\"\n" - "#include \"a_other.h\"\n" - "#include \"important_os_header.h\"", - "c_main.cc")); + verifyFormat("#include \"important_os_header.h\"\n" + "#include \"c_main.h\"\n" + "#include \"a_other.h\"", + sort("#include \"c_main.h\"\n" + "#include \"a_other.h\"\n" + "#include \"important_os_header.h\"", + "c_main.cc")); // check stable when re-run - EXPECT_EQ("#include \"important_os_header.h\"\n" - "#include \"c_main.h\"\n" - "#include \"a_other.h\"", - sort("#include \"important_os_header.h\"\n" - "#include \"c_main.h\"\n" - "#include \"a_other.h\"", - "c_main.cc", 0)); + verifyFormat("#include \"important_os_header.h\"\n" + "#include \"c_main.h\"\n" + "#include \"a_other.h\"", + sort("#include \"important_os_header.h\"\n" + "#include \"c_main.h\"\n" + "#include \"a_other.h\"", + "c_main.cc", 0)); } TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) { @@ -769,34 +769,34 @@ TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) { {".*", 1, 0, false}}; Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; - EXPECT_EQ("#include \"important_os_header.h\"\n" - "\n" - "#include \"c_main.h\"\n" - "\n" - "#include \"a_other.h\"", - sort("#include \"c_main.h\"\n" - "#include \"a_other.h\"\n" - "#include \"important_os_header.h\"", - "c_main.cc")); + verifyFormat("#include \"important_os_header.h\"\n" + "\n" + "#include \"c_main.h\"\n" + "\n" + "#include \"a_other.h\"", + sort("#include \"c_main.h\"\n" + "#include \"a_other.h\"\n" + "#include \"important_os_header.h\"", + "c_main.cc")); // check stable when re-run - EXPECT_EQ("#include \"important_os_header.h\"\n" - "\n" - "#include \"c_main.h\"\n" - "\n" - "#include \"a_other.h\"", - sort("#include \"important_os_header.h\"\n" - "\n" - "#include \"c_main.h\"\n" - "\n" - "#include \"a_other.h\"", - "c_main.cc", 0)); + verifyFormat("#include \"important_os_header.h\"\n" + "\n" + "#include \"c_main.h\"\n" + "\n" + "#include \"a_other.h\"", + sort("#include \"important_os_header.h\"\n" + "\n" + "#include \"c_main.h\"\n" + "\n" + "#include \"a_other.h\"", + "c_main.cc", 0)); } TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) { - std::string Code = "#include \n" // Start of line: 0 - "#include \n" // Start of line: 15 - "#include \n"; // Start of line: 33 + StringRef Code = "#include \n" // Start of line: 0 + "#include \n" // Start of line: 15 + "#include \n"; // Start of line: 33 EXPECT_EQ(31u, newCursor(Code, 0)); EXPECT_EQ(13u, newCursor(Code, 15)); EXPECT_EQ(0u, newCursor(Code, 33)); @@ -808,14 +808,14 @@ TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) { TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionWithRegrouping) { Style.IncludeBlocks = Style.IBS_Regroup; - std::string Code = "#include \"b\"\n" // Start of line: 0 - "\n" // Start of line: 13 - "#include \"aa\"\n" // Start of line: 14 - "int i;"; // Start of line: 28 - std::string Expected = "#include \"aa\"\n" // Start of line: 0 - "#include \"b\"\n" // Start of line: 14 - "int i;"; // Start of line: 27 - EXPECT_EQ(Expected, sort(Code)); + StringRef Code = "#include \"b\"\n" // Start of line: 0 + "\n" // Start of line: 13 + "#include \"aa\"\n" // Start of line: 14 + "int i;"; // Start of line: 28 + StringRef Expected = "#include \"aa\"\n" // Start of line: 0 + "#include \"b\"\n" // Start of line: 14 + "int i;"; // Start of line: 27 + verifyFormat(Expected, sort(Code)); EXPECT_EQ(12u, newCursor(Code, 26)); // Closing quote of "aa" EXPECT_EQ(26u, newCursor(Code, 27)); // Newline after "aa" EXPECT_EQ(27u, newCursor(Code, 28)); // Start of last line @@ -827,14 +827,14 @@ TEST_F(SortIncludesTest, FmtStyle.LineEnding = FormatStyle::LE_CRLF; Style.IncludeCategories = { {"^\"a\"", 0, 0, false}, {"^\"b\"", 1, 1, false}, {".*", 2, 2, false}}; - std::string Code = "#include \"a\"\r\n" // Start of line: 0 - "\r\n" // Start of line: 14 - "#include \"b\"\r\n" // Start of line: 16 - "\r\n" // Start of line: 30 - "#include \"c\"\r\n" // Start of line: 32 - "\r\n" // Start of line: 46 - "int i;"; // Start of line: 48 - verifyNoChange(Code); + StringRef Code = "#include \"a\"\r\n" // Start of line: 0 + "\r\n" // Start of line: 14 + "#include \"b\"\r\n" // Start of line: 16 + "\r\n" // Start of line: 30 + "#include \"c\"\r\n" // Start of line: 32 + "\r\n" // Start of line: 46 + "int i;"; // Start of line: 48 + verifyFormat(Code); EXPECT_EQ(0u, newCursor(Code, 0)); EXPECT_EQ(14u, newCursor(Code, 14)); EXPECT_EQ(16u, newCursor(Code, 16)); @@ -850,19 +850,19 @@ TEST_F( Style.IncludeBlocks = Style.IBS_Regroup; FmtStyle.LineEnding = FormatStyle::LE_CRLF; Style.IncludeCategories = {{".*", 0, 0, false}}; - std::string Code = "#include \"a\"\r\n" // Start of line: 0 - "\r\n" // Start of line: 14 - "#include \"b\"\r\n" // Start of line: 16 - "\r\n" // Start of line: 30 - "#include \"c\"\r\n" // Start of line: 32 - "\r\n" // Start of line: 46 - "int i;"; // Start of line: 48 - std::string Expected = "#include \"a\"\r\n" // Start of line: 0 - "#include \"b\"\r\n" // Start of line: 14 - "#include \"c\"\r\n" // Start of line: 28 - "\r\n" // Start of line: 42 - "int i;"; // Start of line: 44 - EXPECT_EQ(Expected, sort(Code)); + StringRef Code = "#include \"a\"\r\n" // Start of line: 0 + "\r\n" // Start of line: 14 + "#include \"b\"\r\n" // Start of line: 16 + "\r\n" // Start of line: 30 + "#include \"c\"\r\n" // Start of line: 32 + "\r\n" // Start of line: 46 + "int i;"; // Start of line: 48 + StringRef Expected = "#include \"a\"\r\n" // Start of line: 0 + "#include \"b\"\r\n" // Start of line: 14 + "#include \"c\"\r\n" // Start of line: 28 + "\r\n" // Start of line: 42 + "int i;"; // Start of line: 44 + verifyFormat(Expected, sort(Code)); EXPECT_EQ(0u, newCursor(Code, 0)); EXPECT_EQ( 14u, @@ -885,19 +885,19 @@ TEST_F( FmtStyle.LineEnding = FormatStyle::LE_CRLF; Style.IncludeCategories = { {"^\"a\"", 0, 0, false}, {"^\"b\"", 1, 1, false}, {".*", 2, 2, false}}; - std::string Code = "#include \"a\"\r\n" // Start of line: 0 - "#include \"b\"\r\n" // Start of line: 14 - "#include \"c\"\r\n" // Start of line: 28 - "\r\n" // Start of line: 42 - "int i;"; // Start of line: 44 - std::string Expected = "#include \"a\"\r\n" // Start of line: 0 - "\r\n" // Start of line: 14 - "#include \"b\"\r\n" // Start of line: 16 - "\r\n" // Start of line: 30 - "#include \"c\"\r\n" // Start of line: 32 - "\r\n" // Start of line: 46 - "int i;"; // Start of line: 48 - EXPECT_EQ(Expected, sort(Code)); + StringRef Code = "#include \"a\"\r\n" // Start of line: 0 + "#include \"b\"\r\n" // Start of line: 14 + "#include \"c\"\r\n" // Start of line: 28 + "\r\n" // Start of line: 42 + "int i;"; // Start of line: 44 + StringRef Expected = "#include \"a\"\r\n" // Start of line: 0 + "\r\n" // Start of line: 14 + "#include \"b\"\r\n" // Start of line: 16 + "\r\n" // Start of line: 30 + "#include \"c\"\r\n" // Start of line: 32 + "\r\n" // Start of line: 46 + "int i;"; // Start of line: 48 + verifyFormat(Expected, sort(Code)); EXPECT_EQ(0u, newCursor(Code, 0)); EXPECT_EQ(15u, newCursor(Code, 16)); EXPECT_EQ(30u, newCursor(Code, 32)); @@ -912,21 +912,21 @@ TEST_F( FmtStyle.LineEnding = FormatStyle::LE_CRLF; Style.IncludeCategories = { {"^\"a\"", 0, 0, false}, {"^\"b\"", 1, 1, false}, {".*", 2, 2, false}}; - std::string Code = "#include \"a\"\r\n" // Start of line: 0 - "\r\n" // Start of line: 14 - "#include \"c\"\r\n" // Start of line: 16 - "\r\n" // Start of line: 30 - "#include \"b\"\r\n" // Start of line: 32 - "\r\n" // Start of line: 46 - "int i;"; // Start of line: 48 - std::string Expected = "#include \"a\"\r\n" // Start of line: 0 - "\r\n" // Start of line: 14 - "#include \"b\"\r\n" // Start of line: 16 - "\r\n" // Start of line: 30 - "#include \"c\"\r\n" // Start of line: 32 - "\r\n" // Start of line: 46 - "int i;"; // Start of line: 48 - EXPECT_EQ(Expected, sort(Code)); + StringRef Code = "#include \"a\"\r\n" // Start of line: 0 + "\r\n" // Start of line: 14 + "#include \"c\"\r\n" // Start of line: 16 + "\r\n" // Start of line: 30 + "#include \"b\"\r\n" // Start of line: 32 + "\r\n" // Start of line: 46 + "int i;"; // Start of line: 48 + StringRef Expected = "#include \"a\"\r\n" // Start of line: 0 + "\r\n" // Start of line: 14 + "#include \"b\"\r\n" // Start of line: 16 + "\r\n" // Start of line: 30 + "#include \"c\"\r\n" // Start of line: 32 + "\r\n" // Start of line: 46 + "int i;"; // Start of line: 48 + verifyFormat(Expected, sort(Code)); EXPECT_EQ(0u, newCursor(Code, 0)); EXPECT_EQ(14u, newCursor(Code, 14)); EXPECT_EQ(30u, newCursor(Code, 32)); @@ -938,88 +938,88 @@ TEST_F( #endif TEST_F(SortIncludesTest, DeduplicateIncludes) { - EXPECT_EQ("#include \n" - "#include \n" - "#include ", - sort("#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include ")); + verifyFormat("#include \n" + "#include \n" + "#include ", + sort("#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include ")); Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; - EXPECT_EQ("#include \n" - "#include \n" - "#include ", - sort("#include \n" - "#include \n" - "\n" - "#include \n" - "\n" - "#include \n" - "#include ")); + verifyFormat("#include \n" + "#include \n" + "#include ", + sort("#include \n" + "#include \n" + "\n" + "#include \n" + "\n" + "#include \n" + "#include ")); Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; - EXPECT_EQ("#include \n" - "#include \n" - "#include ", - sort("#include \n" - "#include \n" - "\n" - "#include \n" - "\n" - "#include \n" - "#include ")); + verifyFormat("#include \n" + "#include \n" + "#include ", + sort("#include \n" + "#include \n" + "\n" + "#include \n" + "\n" + "#include \n" + "#include ")); } TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) { - EXPECT_EQ("#include \n" - "#include \n" - "#include ", - sort("#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include ")); + verifyFormat("#include \n" + "#include \n" + "#include ", + sort("#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include ")); Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; - EXPECT_EQ("#include \n" - "#include \n" - "#include ", - sort("#include \n" - "#include \n" - "\n" - "#include \n" - "\n" - "#include \n" - "#include ")); + verifyFormat("#include \n" + "#include \n" + "#include ", + sort("#include \n" + "#include \n" + "\n" + "#include \n" + "\n" + "#include \n" + "#include ")); Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; - EXPECT_EQ("#include \n" - "#include \n" - "#include ", - sort("#include \n" - "#include \n" - "\n" - "#include \n" - "\n" - "#include \n" - "#include ")); + verifyFormat("#include \n" + "#include \n" + "#include ", + sort("#include \n" + "#include \n" + "\n" + "#include \n" + "\n" + "#include \n" + "#include ")); } TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionAfterDeduplicate) { - std::string Code = "#include \n" // Start of line: 0 - "#include \n" // Start of line: 13 - "#include \n" // Start of line: 26 - "#include \n" // Start of line: 39 - "#include \n" // Start of line: 52 - "#include \n"; // Start of line: 65 - std::string Expected = "#include \n" // Start of line: 0 - "#include \n" // Start of line: 13 - "#include \n"; // Start of line: 26 - EXPECT_EQ(Expected, sort(Code)); + StringRef Code = "#include \n" // Start of line: 0 + "#include \n" // Start of line: 13 + "#include \n" // Start of line: 26 + "#include \n" // Start of line: 39 + "#include \n" // Start of line: 52 + "#include \n"; // Start of line: 65 + StringRef Expected = "#include \n" // Start of line: 0 + "#include \n" // Start of line: 13 + "#include \n"; // Start of line: 26 + verifyFormat(Expected, sort(Code)); // Cursor on 'i' in "#include ". EXPECT_EQ(1u, newCursor(Code, 14)); // Cursor on 'b' in "#include ". @@ -1033,26 +1033,26 @@ TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionAfterDeduplicate) { } TEST_F(SortIncludesTest, DeduplicateLocallyInEachBlock) { - EXPECT_EQ("#include \n" - "#include \n" - "\n" - "#include \n" - "#include ", - sort("#include \n" - "#include \n" - "\n" - "#include \n" - "#include \n" - "#include ")); + verifyFormat("#include \n" + "#include \n" + "\n" + "#include \n" + "#include ", + sort("#include \n" + "#include \n" + "\n" + "#include \n" + "#include \n" + "#include ")); } TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) { - std::string Code = "#include \n" - "#include \n" - "#include \n" - "#include \n" - "\n" - " int x ;"; + StringRef Code = "#include \n" + "#include \n" + "#include \n" + "#include \n" + "\n" + " int x ;"; std::vector Ranges = {tooling::Range(0, 52)}; auto Replaces = sortIncludes(FmtStyle, Code, Ranges, "input.cpp"); Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); @@ -1062,80 +1062,78 @@ TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) { } TEST_F(SortIncludesTest, DoNotSortLikelyXml) { - EXPECT_EQ("", - sort("", - "input.h", 0)); + verifyFormat("", + sort("", + "input.h", 0)); } TEST_F(SortIncludesTest, DoNotOutputReplacementsForSortedBlocksWithRegrouping) { Style.IncludeBlocks = Style.IBS_Regroup; - std::string Code = R"( -#include "b.h" - -#include -)"; - EXPECT_EQ(Code, sort(Code, "input.h", 0)); + StringRef Code = "#include \"b.h\"\n" + "\n" + "#include "; + verifyFormat(Code, sort(Code, "input.h", 0)); } TEST_F(SortIncludesTest, DoNotOutputReplacementsForSortedBlocksWithRegroupingWindows) { Style.IncludeBlocks = Style.IBS_Regroup; - std::string Code = "#include \"b.h\"\r\n" - "\r\n" - "#include \r\n"; - EXPECT_EQ(Code, sort(Code, "input.h", 0)); + StringRef Code = "#include \"b.h\"\r\n" + "\r\n" + "#include \r\n"; + verifyFormat(Code, sort(Code, "input.h", 0)); } TEST_F(SortIncludesTest, MainIncludeChar) { - std::string Code = "#include \n" - "#include \"quote/input.h\"\n" - "#include \n"; + StringRef Code = "#include \n" + "#include \"quote/input.h\"\n" + "#include \n"; // Default behavior - EXPECT_EQ("#include \"quote/input.h\"\n" - "#include \n" - "#include \n", - sort(Code, "input.cc", 1)); + verifyFormat("#include \"quote/input.h\"\n" + "#include \n" + "#include \n", + sort(Code, "input.cc", 1)); Style.MainIncludeChar = tooling::IncludeStyle::MICD_Quote; - EXPECT_EQ("#include \"quote/input.h\"\n" - "#include \n" - "#include \n", - sort(Code, "input.cc", 1)); + verifyFormat("#include \"quote/input.h\"\n" + "#include \n" + "#include \n", + sort(Code, "input.cc", 1)); Style.MainIncludeChar = tooling::IncludeStyle::MICD_AngleBracket; - EXPECT_EQ("#include \n" - "#include \"quote/input.h\"\n" - "#include \n", - sort(Code, "input.cc", 1)); + verifyFormat("#include \n" + "#include \"quote/input.h\"\n" + "#include \n", + sort(Code, "input.cc", 1)); } TEST_F(SortIncludesTest, MainIncludeCharAnyPickQuote) { Style.MainIncludeChar = tooling::IncludeStyle::MICD_Any; - EXPECT_EQ("#include \"input.h\"\n" - "#include \n" - "#include \n", - sort("#include \n" - "#include \"input.h\"\n" - "#include \n", - "input.cc", 1)); + verifyFormat("#include \"input.h\"\n" + "#include \n" + "#include \n", + sort("#include \n" + "#include \"input.h\"\n" + "#include \n", + "input.cc", 1)); } TEST_F(SortIncludesTest, MainIncludeCharAnyPickAngleBracket) { Style.MainIncludeChar = tooling::IncludeStyle::MICD_Any; - EXPECT_EQ("#include \n" - "#include \n" - "#include \n", - sort("#include \n" - "#include \n" - "#include \n", - "input.cc", 1)); + verifyFormat("#include \n" + "#include \n" + "#include \n", + sort("#include \n" + "#include \n" + "#include \n", + "input.cc", 1)); } TEST_F(SortIncludesTest, MainIncludeCharQuoteAndRegroup) { @@ -1144,28 +1142,28 @@ TEST_F(SortIncludesTest, MainIncludeCharQuoteAndRegroup) { Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; Style.MainIncludeChar = tooling::IncludeStyle::MICD_Quote; - EXPECT_EQ("#include \"lib-b/input.h\"\n" - "\n" - "#include \n" - "#include \n" - "#include \n" - "\n" - "#include \n" - "#include \n" - "\n" - "#include \n" - "#include \n" - "#include \n", - sort("#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \"lib-b/input.h\"\n" - "#include \n" - "#include \n" - "#include \n" - "#include \n", - "input.cc")); + verifyFormat("#include \"lib-b/input.h\"\n" + "\n" + "#include \n" + "#include \n" + "#include \n" + "\n" + "#include \n" + "#include \n" + "\n" + "#include \n" + "#include \n" + "#include \n", + sort("#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \"lib-b/input.h\"\n" + "#include \n" + "#include \n" + "#include \n" + "#include \n", + "input.cc")); } TEST_F(SortIncludesTest, MainIncludeCharAngleBracketAndRegroup) { @@ -1174,60 +1172,60 @@ TEST_F(SortIncludesTest, MainIncludeCharAngleBracketAndRegroup) { Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; Style.MainIncludeChar = tooling::IncludeStyle::MICD_AngleBracket; - EXPECT_EQ("#include \n" - "\n" - "#include \n" - "#include \n" - "\n" - "#include \"lib-b/input.h\"\n" - "#include \n" - "#include \n" - "\n" - "#include \n" - "#include \n" - "#include \n", - sort("#include \n" - "#include \n" - "#include \n" - "#include \n" - "#include \"lib-b/input.h\"\n" - "#include \n" - "#include \n" - "#include \n" - "#include \n", - "input.cc")); + verifyFormat("#include \n" + "\n" + "#include \n" + "#include \n" + "\n" + "#include \"lib-b/input.h\"\n" + "#include \n" + "#include \n" + "\n" + "#include \n" + "#include \n" + "#include \n", + sort("#include \n" + "#include \n" + "#include \n" + "#include \n" + "#include \"lib-b/input.h\"\n" + "#include \n" + "#include \n" + "#include \n" + "#include \n", + "input.cc")); } TEST_F(SortIncludesTest, DoNotRegroupGroupsInGoogleObjCStyle) { FmtStyle = getGoogleStyle(FormatStyle::LK_ObjC); - EXPECT_EQ("#include \n" - "#include \n" - "#include \"a.h\"", - sort("#include \n" - "#include \n" - "#include \"a.h\"")); + verifyFormat("#include \n" + "#include \n" + "#include \"a.h\"", + sort("#include \n" + "#include \n" + "#include \"a.h\"")); } TEST_F(SortIncludesTest, DoNotTreatPrecompiledHeadersAsFirstBlock) { Style.IncludeBlocks = Style.IBS_Merge; - std::string Code = "#include \"d.h\"\r\n" - "#include \"b.h\"\r\n" - "#pragma hdrstop\r\n" - "\r\n" - "#include \"c.h\"\r\n" - "#include \"a.h\"\r\n" - "#include \"e.h\"\r\n"; - - std::string Expected = "#include \"b.h\"\r\n" - "#include \"d.h\"\r\n" - "#pragma hdrstop\r\n" - "\r\n" - "#include \"e.h\"\r\n" - "#include \"a.h\"\r\n" - "#include \"c.h\"\r\n"; - - EXPECT_EQ(Expected, sort(Code, "e.cpp", 2)); + StringRef Code = "#include \"d.h\"\r\n" + "#include \"b.h\"\r\n" + "#pragma hdrstop\r\n" + "\r\n" + "#include \"c.h\"\r\n" + "#include \"a.h\"\r\n" + "#include \"e.h\"\r\n"; + + StringRef Expected = "#include \"b.h\"\r\n" + "#include \"d.h\"\r\n" + "#pragma hdrstop\r\n" + "\r\n" + "#include \"e.h\"\r\n" + "#include \"a.h\"\r\n" + "#include \"c.h\"\r\n"; + + verifyFormat(Expected, sort(Code, "e.cpp", 2)); Code = "#include \"d.h\"\n" "#include \"b.h\"\n" @@ -1245,59 +1243,59 @@ TEST_F(SortIncludesTest, DoNotTreatPrecompiledHeadersAsFirstBlock) { "#include \"a.h\"\n" "#include \"c.h\"\n"; - EXPECT_EQ(Expected, sort(Code, "e.cpp", 2)); + verifyFormat(Expected, sort(Code, "e.cpp", 2)); } TEST_F(SortIncludesTest, skipUTF8ByteOrderMarkMerge) { Style.IncludeBlocks = Style.IBS_Merge; - std::string Code = "\xEF\xBB\xBF#include \"d.h\"\r\n" - "#include \"b.h\"\r\n" - "\r\n" - "#include \"c.h\"\r\n" - "#include \"a.h\"\r\n" - "#include \"e.h\"\r\n"; - - std::string Expected = "\xEF\xBB\xBF#include \"e.h\"\r\n" - "#include \"a.h\"\r\n" - "#include \"b.h\"\r\n" - "#include \"c.h\"\r\n" - "#include \"d.h\"\r\n"; - - EXPECT_EQ(Expected, sort(Code, "e.cpp", 1)); + StringRef Code = "\xEF\xBB\xBF#include \"d.h\"\r\n" + "#include \"b.h\"\r\n" + "\r\n" + "#include \"c.h\"\r\n" + "#include \"a.h\"\r\n" + "#include \"e.h\"\r\n"; + + StringRef Expected = "\xEF\xBB\xBF#include \"e.h\"\r\n" + "#include \"a.h\"\r\n" + "#include \"b.h\"\r\n" + "#include \"c.h\"\r\n" + "#include \"d.h\"\r\n"; + + verifyFormat(Expected, sort(Code, "e.cpp", 1)); } TEST_F(SortIncludesTest, skipUTF8ByteOrderMarkPreserve) { Style.IncludeBlocks = Style.IBS_Preserve; - std::string Code = "\xEF\xBB\xBF#include \"d.h\"\r\n" - "#include \"b.h\"\r\n" - "\r\n" - "#include \"c.h\"\r\n" - "#include \"a.h\"\r\n" - "#include \"e.h\"\r\n"; - - std::string Expected = "\xEF\xBB\xBF#include \"b.h\"\r\n" - "#include \"d.h\"\r\n" - "\r\n" - "#include \"a.h\"\r\n" - "#include \"c.h\"\r\n" - "#include \"e.h\"\r\n"; - - EXPECT_EQ(Expected, sort(Code, "e.cpp", 2)); + StringRef Code = "\xEF\xBB\xBF#include \"d.h\"\r\n" + "#include \"b.h\"\r\n" + "\r\n" + "#include \"c.h\"\r\n" + "#include \"a.h\"\r\n" + "#include \"e.h\"\r\n"; + + StringRef Expected = "\xEF\xBB\xBF#include \"b.h\"\r\n" + "#include \"d.h\"\r\n" + "\r\n" + "#include \"a.h\"\r\n" + "#include \"c.h\"\r\n" + "#include \"e.h\"\r\n"; + + verifyFormat(Expected, sort(Code, "e.cpp", 2)); } TEST_F(SortIncludesTest, MergeLines) { Style.IncludeBlocks = Style.IBS_Merge; - std::string Code = "#include \"c.h\"\r\n" - "#include \"b\\\r\n" - ".h\"\r\n" - "#include \"a.h\"\r\n"; + StringRef Code = "#include \"c.h\"\r\n" + "#include \"b\\\r\n" + ".h\"\r\n" + "#include \"a.h\"\r\n"; - std::string Expected = "#include \"a.h\"\r\n" - "#include \"b\\\r\n" - ".h\"\r\n" - "#include \"c.h\"\r\n"; + StringRef Expected = "#include \"a.h\"\r\n" + "#include \"b\\\r\n" + ".h\"\r\n" + "#include \"c.h\"\r\n"; - EXPECT_EQ(Expected, sort(Code, "a.cpp", 1)); + verifyFormat(Expected, sort(Code, "a.cpp", 1)); } TEST_F(SortIncludesTest, DisableFormatDisablesIncludeSorting) { @@ -1305,154 +1303,154 @@ TEST_F(SortIncludesTest, DisableFormatDisablesIncludeSorting) { "#include \n"; StringRef Unsorted = "#include \n" "#include \n"; - EXPECT_EQ(Sorted, sort(Unsorted)); + verifyFormat(Sorted, sort(Unsorted)); FmtStyle.DisableFormat = true; - EXPECT_EQ(Unsorted, sort(Unsorted, "input.cpp", 0)); + verifyFormat(Unsorted, sort(Unsorted, "input.cpp", 0)); } TEST_F(SortIncludesTest, DisableRawStringLiteralSorting) { - EXPECT_EQ("const char *t = R\"(\n" - "#include \n" - "#include \n" - ")\";", - sort("const char *t = R\"(\n" - "#include \n" - "#include \n" - ")\";", - "test.cxx", 0)); - EXPECT_EQ("const char *t = R\"x(\n" - "#include \n" - "#include \n" - ")x\";", - sort("const char *t = R\"x(\n" - "#include \n" - "#include \n" - ")x\";", - "test.cxx", 0)); - EXPECT_EQ("const char *t = R\"xyz(\n" - "#include \n" - "#include \n" - ")xyz\";", - sort("const char *t = R\"xyz(\n" - "#include \n" - "#include \n" - ")xyz\";", - "test.cxx", 0)); - - EXPECT_EQ("#include \n" - "#include \n" - "const char *t = R\"(\n" - "#include \n" - "#include \n" - ")\";\n" - "#include \n" - "#include \n" - "const char *t = R\"x(\n" - "#include \n" - "#include \n" - ")x\";\n" - "#include \n" - "#include \n" - "const char *t = R\"xyz(\n" - "#include \n" - "#include \n" - ")xyz\";\n" - "#include \n" - "#include ", - sort("#include \n" - "#include \n" - "const char *t = R\"(\n" - "#include \n" - "#include \n" - ")\";\n" - "#include \n" - "#include \n" - "const char *t = R\"x(\n" - "#include \n" - "#include \n" - ")x\";\n" - "#include \n" - "#include \n" - "const char *t = R\"xyz(\n" - "#include \n" - "#include \n" - ")xyz\";\n" - "#include \n" - "#include ", - "test.cc", 4)); - - EXPECT_EQ("const char *t = R\"AMZ029amz(\n" - "#include \n" - "#include \n" - ")AMZ029amz\";", - sort("const char *t = R\"AMZ029amz(\n" - "#include \n" - "#include \n" - ")AMZ029amz\";", - "test.cxx", 0)); - - EXPECT_EQ("const char *t = R\"-AMZ029amz(\n" - "#include \n" - "#include \n" - ")-AMZ029amz\";", - sort("const char *t = R\"-AMZ029amz(\n" - "#include \n" - "#include \n" - ")-AMZ029amz\";", - "test.cxx", 0)); - - EXPECT_EQ("const char *t = R\"AMZ029amz-(\n" - "#include \n" - "#include \n" - ")AMZ029amz-\";", - sort("const char *t = R\"AMZ029amz-(\n" - "#include \n" - "#include \n" - ")AMZ029amz-\";", - "test.cxx", 0)); - - EXPECT_EQ("const char *t = R\"AM|029amz-(\n" - "#include \n" - "#include \n" - ")AM|029amz-\";", - sort("const char *t = R\"AM|029amz-(\n" - "#include \n" - "#include \n" - ")AM|029amz-\";", - "test.cxx", 0)); - - EXPECT_EQ("const char *t = R\"AM[029amz-(\n" - "#include \n" - "#include \n" - ")AM[029amz-\";", - sort("const char *t = R\"AM[029amz-(\n" - "#include \n" - "#include \n" - ")AM[029amz-\";", - "test.cxx", 0)); - - EXPECT_EQ("const char *t = R\"AM]029amz-(\n" - "#include \n" - "#include \n" - ")AM]029amz-\";", - sort("const char *t = R\"AM]029amz-(\n" - "#include \n" - "#include \n" - ")AM]029amz-\";", - "test.cxx", 0)); + verifyFormat("const char *t = R\"(\n" + "#include \n" + "#include \n" + ")\";", + sort("const char *t = R\"(\n" + "#include \n" + "#include \n" + ")\";", + "test.cxx", 0)); + verifyFormat("const char *t = R\"x(\n" + "#include \n" + "#include \n" + ")x\";", + sort("const char *t = R\"x(\n" + "#include \n" + "#include \n" + ")x\";", + "test.cxx", 0)); + verifyFormat("const char *t = R\"xyz(\n" + "#include \n" + "#include \n" + ")xyz\";", + sort("const char *t = R\"xyz(\n" + "#include \n" + "#include \n" + ")xyz\";", + "test.cxx", 0)); + + verifyFormat("#include \n" + "#include \n" + "const char *t = R\"(\n" + "#include \n" + "#include \n" + ")\";\n" + "#include \n" + "#include \n" + "const char *t = R\"x(\n" + "#include \n" + "#include \n" + ")x\";\n" + "#include \n" + "#include \n" + "const char *t = R\"xyz(\n" + "#include \n" + "#include \n" + ")xyz\";\n" + "#include \n" + "#include ", + sort("#include \n" + "#include \n" + "const char *t = R\"(\n" + "#include \n" + "#include \n" + ")\";\n" + "#include \n" + "#include \n" + "const char *t = R\"x(\n" + "#include \n" + "#include \n" + ")x\";\n" + "#include \n" + "#include \n" + "const char *t = R\"xyz(\n" + "#include \n" + "#include \n" + ")xyz\";\n" + "#include \n" + "#include ", + "test.cc", 4)); + + verifyFormat("const char *t = R\"AMZ029amz(\n" + "#include \n" + "#include \n" + ")AMZ029amz\";", + sort("const char *t = R\"AMZ029amz(\n" + "#include \n" + "#include \n" + ")AMZ029amz\";", + "test.cxx", 0)); + + verifyFormat("const char *t = R\"-AMZ029amz(\n" + "#include \n" + "#include \n" + ")-AMZ029amz\";", + sort("const char *t = R\"-AMZ029amz(\n" + "#include \n" + "#include \n" + ")-AMZ029amz\";", + "test.cxx", 0)); + + verifyFormat("const char *t = R\"AMZ029amz-(\n" + "#include \n" + "#include \n" + ")AMZ029amz-\";", + sort("const char *t = R\"AMZ029amz-(\n" + "#include \n" + "#include \n" + ")AMZ029amz-\";", + "test.cxx", 0)); + + verifyFormat("const char *t = R\"AM|029amz-(\n" + "#include \n" + "#include \n" + ")AM|029amz-\";", + sort("const char *t = R\"AM|029amz-(\n" + "#include \n" + "#include \n" + ")AM|029amz-\";", + "test.cxx", 0)); + + verifyFormat("const char *t = R\"AM[029amz-(\n" + "#include \n" + "#include \n" + ")AM[029amz-\";", + sort("const char *t = R\"AM[029amz-(\n" + "#include \n" + "#include \n" + ")AM[029amz-\";", + "test.cxx", 0)); + + verifyFormat("const char *t = R\"AM]029amz-(\n" + "#include \n" + "#include \n" + ")AM]029amz-\";", + sort("const char *t = R\"AM]029amz-(\n" + "#include \n" + "#include \n" + ")AM]029amz-\";", + "test.cxx", 0)); #define X "AMZ029amz{}+!%*=_:;',.<>|/?#~-$" - EXPECT_EQ("const char *t = R\"" X "(\n" - "#include \n" - "#include \n" - ")" X "\";", - sort("const char *t = R\"" X "(\n" - "#include \n" - "#include \n" - ")" X "\";", - "test.cxx", 0)); + verifyFormat("const char *t = R\"" X "(\n" + "#include \n" + "#include \n" + ")" X "\";", + sort("const char *t = R\"" X "(\n" + "#include \n" + "#include \n" + ")" X "\";", + "test.cxx", 0)); #undef X } -- GitLab From 2f52bbeb6f6f3b7abef19cb5297773d95aa0b434 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Sun, 19 May 2024 15:20:46 -0700 Subject: [PATCH 041/793] [mlir] Use operator==(StringRef, StringRef) (NFC) (#92706) --- .../SparseTensor/IR/Detail/LvlTypeParser.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mlir/lib/Dialect/SparseTensor/IR/Detail/LvlTypeParser.cpp b/mlir/lib/Dialect/SparseTensor/IR/Detail/LvlTypeParser.cpp index 39f5cf1a7508..bb6c65a6f6ca 100644 --- a/mlir/lib/Dialect/SparseTensor/IR/Detail/LvlTypeParser.cpp +++ b/mlir/lib/Dialect/SparseTensor/IR/Detail/LvlTypeParser.cpp @@ -37,7 +37,7 @@ FailureOr LvlTypeParser::parseLvlType(AsmParser &parser) const { uint64_t properties = 0; SmallVector structured; - if (base.compare("structured") == 0) { + if (base == "structured") { ParseResult res = parser.parseCommaSeparatedList( mlir::OpAsmParser::Delimiter::OptionalSquare, [&]() -> ParseResult { return parseStructured(parser, &structured); }, @@ -60,18 +60,18 @@ FailureOr LvlTypeParser::parseLvlType(AsmParser &parser) const { FAILURE_IF_FAILED(res) // Set the base bit for properties. - if (base.compare("dense") == 0) { + if (base == "dense") { properties |= static_cast(LevelFormat::Dense); - } else if (base.compare("batch") == 0) { + } else if (base == "batch") { properties |= static_cast(LevelFormat::Batch); - } else if (base.compare("compressed") == 0) { + } else if (base == "compressed") { properties |= static_cast(LevelFormat::Compressed); - } else if (base.compare("structured") == 0) { + } else if (base == "structured") { properties |= static_cast(LevelFormat::NOutOfM); properties |= nToBits(structured[0]) | mToBits(structured[1]); - } else if (base.compare("loose_compressed") == 0) { + } else if (base == "loose_compressed") { properties |= static_cast(LevelFormat::LooseCompressed); - } else if (base.compare("singleton") == 0) { + } else if (base == "singleton") { properties |= static_cast(LevelFormat::Singleton); } else { parser.emitError(loc, "unknown level format: ") << base; -- GitLab From 5d3f296733b66281a53dd451a983e69ae0bb482f Mon Sep 17 00:00:00 2001 From: Mingming Liu Date: Sun, 19 May 2024 16:33:17 -0700 Subject: [PATCH 042/793] [CallPromotionUtils]Implement conditional indirect call promotion with vtable-based comparison (#81378) * Given the code sequence ``` bb: %vtable = load ptr, ptr %d, !prof !8 %vfn = getelementptr inbounds ptr, ptr %vtable, i64 1 %1 = load ptr, ptr %vfn %call = tail call i32 %1(ptr %d), !prof !9 ``` The transformation looks like ``` bb: %vtable = load ptr, ptr %d, align 8 %vfn = getelementptr inbounds i8, ptr %vtable, i64 8 <-- Inst 1 %func-addr = load ptr, ptr %vfn, align 8 <-- Inst 2 # compare loaded pointers with address point of vtables %1 = icmp eq ptr %vtable, getelementptr inbounds (i8, ptr @_ZTV, i32 16) br i1 %1, label %if.true.direct_targ, label %if.false.orig_indirect, !prof !18 if.true.direct_targ: ; preds = %bb %2 = tail call i32 @(ptr nonnull %d) br label %if.end.icp if.false.orig_indirect: ; preds = %bb %call = tail call i32 %func-addr(ptr nonnull %d) br label %if.end.icp if.end.icp: ; preds = %if.false.orig_indirect, %if.true.direct_targ %4 = phi i32 [ %call, %if.false.orig_indirect ], [ %2, %if.true.direct_targ ] ``` It's intentional that `Inst 1` and `Inst2` remains in `bb` (not in `if.false.orig_indirect`). A follow up patch will implement code to sink them (something like how `instcombine` would [sink](https://github.com/llvm/llvm-project/blob/2fcfc9754a16805b81e541dc8222a8b5cf17a121/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp#L4293) instructions along with [debug intrinsics](https://github.com/llvm/llvm-project/blob/2fcfc9754a16805b81e541dc8222a8b5cf17a121/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp#L4356-L4368) if possible) * The parent patch is https://github.com/llvm/llvm-project/pull/81181 --- .../Transforms/Utils/CallPromotionUtils.h | 33 +++++-- .../Transforms/Utils/CallPromotionUtils.cpp | 32 ++++++- .../Utils/CallPromotionUtilsTest.cpp | 88 +++++++++++++++++++ 3 files changed, 143 insertions(+), 10 deletions(-) diff --git a/llvm/include/llvm/Transforms/Utils/CallPromotionUtils.h b/llvm/include/llvm/Transforms/Utils/CallPromotionUtils.h index fcb384ec3613..385831f45703 100644 --- a/llvm/include/llvm/Transforms/Utils/CallPromotionUtils.h +++ b/llvm/include/llvm/Transforms/Utils/CallPromotionUtils.h @@ -15,9 +15,12 @@ #define LLVM_TRANSFORMS_UTILS_CALLPROMOTIONUTILS_H namespace llvm { +template class ArrayRef; +class Constant; class CallBase; class CastInst; class Function; +class Instruction; class MDNode; class Value; @@ -41,7 +44,9 @@ bool isLegalToPromote(const CallBase &CB, Function *Callee, CallBase &promoteCall(CallBase &CB, Function *Callee, CastInst **RetBitCast = nullptr); -/// Promote the given indirect call site to conditionally call \p Callee. +/// Promote the given indirect call site to conditionally call \p Callee. The +/// promoted direct call instruction is predicated on `CB.getCalledOperand() == +/// Callee`. /// /// This function creates an if-then-else structure at the location of the call /// site. The original call site is moved into the "else" block. A clone of the @@ -51,6 +56,22 @@ CallBase &promoteCall(CallBase &CB, Function *Callee, CallBase &promoteCallWithIfThenElse(CallBase &CB, Function *Callee, MDNode *BranchWeights = nullptr); +/// This is similar to `promoteCallWithIfThenElse` except that the condition to +/// promote a virtual call is that \p VPtr is the same as any of \p +/// AddressPoints. +/// +/// This function is expected to be used on virtual calls (a subset of indirect +/// calls). \p VPtr is the virtual table address stored in the objects, and +/// \p AddressPoints contains vtable address points. A vtable address point is +/// a location inside the vtable that's referenced by vpointer in C++ objects. +/// +/// TODO: sink the address-calculation instructions of indirect callee to the +/// indirect call fallback after transformation. +CallBase &promoteCallWithVTableCmp(CallBase &CB, Instruction *VPtr, + Function *Callee, + ArrayRef AddressPoints, + MDNode *BranchWeights); + /// Try to promote (devirtualize) a virtual call on an Alloca. Return true on /// success. /// @@ -76,11 +97,11 @@ bool tryPromoteCall(CallBase &CB); /// Predicate and clone the given call site. /// -/// This function creates an if-then-else structure at the location of the call -/// site. The "if" condition compares the call site's called value to the given -/// callee. The original call site is moved into the "else" block, and a clone -/// of the call site is placed in the "then" block. The cloned instruction is -/// returned. +/// This function creates an if-then-else structure at the location of the +/// call site. The "if" condition compares the call site's called value to +/// the given callee. The original call site is moved into the "else" block, +/// and a clone of the call site is placed in the "then" block. The cloned +/// instruction is returned. CallBase &versionCallSite(CallBase &CB, Value *Callee, MDNode *BranchWeights); } // end namespace llvm diff --git a/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp b/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp index 9ca9aaf9ee9d..dda80d419999 100644 --- a/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp +++ b/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp @@ -12,9 +12,11 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Utils/CallPromotionUtils.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Analysis/Loads.h" #include "llvm/Analysis/TypeMetadataUtils.h" #include "llvm/IR/AttributeMask.h" +#include "llvm/IR/Constant.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" @@ -188,9 +190,9 @@ static void createRetBitCast(CallBase &CB, Type *RetTy, CastInst **RetBitCast) { /// Predicate and clone the given call site. /// /// This function creates an if-then-else structure at the location of the call -/// site. The "if" condition is specified by `Cond`. The original call site is -/// moved into the "else" block, and a clone of the call site is placed in the -/// "then" block. The cloned instruction is returned. +/// site. The "if" condition is specified by `Cond`. +/// The original call site is moved into the "else" block, and a clone of the +/// call site is placed in the "then" block. The cloned instruction is returned. /// /// For example, the call instruction below: /// @@ -518,7 +520,8 @@ CallBase &llvm::promoteCall(CallBase &CB, Function *Callee, Type *FormalTy = CalleeType->getParamType(ArgNo); Type *ActualTy = Arg->getType(); if (FormalTy != ActualTy) { - auto *Cast = CastInst::CreateBitOrPointerCast(Arg, FormalTy, "", CB.getIterator()); + auto *Cast = + CastInst::CreateBitOrPointerCast(Arg, FormalTy, "", CB.getIterator()); CB.setArgOperand(ArgNo, Cast); // Remove any incompatible attributes for the argument. @@ -568,6 +571,27 @@ CallBase &llvm::promoteCallWithIfThenElse(CallBase &CB, Function *Callee, return promoteCall(NewInst, Callee); } +CallBase &llvm::promoteCallWithVTableCmp(CallBase &CB, Instruction *VPtr, + Function *Callee, + ArrayRef AddressPoints, + MDNode *BranchWeights) { + assert(!AddressPoints.empty() && "Caller should guarantee"); + IRBuilder<> Builder(&CB); + SmallVector ICmps; + for (auto &AddressPoint : AddressPoints) + ICmps.push_back(Builder.CreateICmpEQ(VPtr, AddressPoint)); + + // TODO: Perform tree height reduction if the number of ICmps is high. + Value *Cond = Builder.CreateOr(ICmps); + + // Version the indirect call site. If Cond is true, 'NewInst' will be + // executed, otherwise the original call site will be executed. + CallBase &NewInst = versionCallSiteWithCond(CB, Cond, BranchWeights); + + // Promote 'NewInst' so that it directly calls the desired function. + return promoteCall(NewInst, Callee); +} + bool llvm::tryPromoteCall(CallBase &CB) { assert(!CB.getCalledFunction()); Module *M = CB.getCaller()->getParent(); diff --git a/llvm/unittests/Transforms/Utils/CallPromotionUtilsTest.cpp b/llvm/unittests/Transforms/Utils/CallPromotionUtilsTest.cpp index 0e9641c5846f..2d457eb3b678 100644 --- a/llvm/unittests/Transforms/Utils/CallPromotionUtilsTest.cpp +++ b/llvm/unittests/Transforms/Utils/CallPromotionUtilsTest.cpp @@ -8,9 +8,12 @@ #include "llvm/Transforms/Utils/CallPromotionUtils.h" #include "llvm/AsmParser/Parser.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/MDBuilder.h" #include "llvm/IR/Module.h" +#include "llvm/IR/NoFolder.h" #include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" @@ -24,6 +27,21 @@ static std::unique_ptr parseIR(LLVMContext &C, const char *IR) { return Mod; } +// Returns a constant representing the vtable's address point specified by the +// offset. +static Constant *getVTableAddressPointOffset(GlobalVariable *VTable, + uint32_t AddressPointOffset) { + Module &M = *VTable->getParent(); + LLVMContext &Context = M.getContext(); + assert(AddressPointOffset < + M.getDataLayout().getTypeAllocSize(VTable->getValueType()) && + "Out-of-bound access"); + + return ConstantExpr::getInBoundsGetElementPtr( + Type::getInt8Ty(Context), VTable, + llvm::ConstantInt::get(Type::getInt32Ty(Context), AddressPointOffset)); +} + TEST(CallPromotionUtilsTest, TryPromoteCall) { LLVMContext C; std::unique_ptr M = parseIR(C, @@ -368,3 +386,73 @@ declare %struct2 @_ZN4Impl3RunEv(%class.Impl* %this) bool IsPromoted = tryPromoteCall(*CI); EXPECT_FALSE(IsPromoted); } + +TEST(CallPromotionUtilsTest, promoteCallWithVTableCmp) { + LLVMContext C; + std::unique_ptr M = parseIR(C, + R"IR( +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@_ZTV5Base1 = constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr null, ptr @_ZN5Base15func0Ev, ptr @_ZN5Base15func1Ev] }, !type !0 +@_ZTV8Derived1 = constant { [4 x ptr], [3 x ptr] } { [4 x ptr] [ptr inttoptr (i64 -8 to ptr), ptr null, ptr @_ZN5Base15func0Ev, ptr @_ZN5Base15func1Ev], [3 x ptr] [ptr null, ptr null, ptr @_ZN5Base25func2Ev] }, !type !0, !type !1, !type !2 +@_ZTV8Derived2 = constant { [3 x ptr], [3 x ptr], [4 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @_ZN5Base35func3Ev], [3 x ptr] [ptr inttoptr (i64 -8 to ptr), ptr null, ptr @_ZN5Base25func2Ev], [4 x ptr] [ptr inttoptr (i64 -16 to ptr), ptr null, ptr @_ZN5Base15func0Ev, ptr @_ZN5Base15func1Ev] }, !type !3, !type !4, !type !5, !type !6 + +define i32 @testfunc(ptr %d) { +entry: + %vtable = load ptr, ptr %d, !prof !7 + %vfn = getelementptr inbounds ptr, ptr %vtable, i64 1 + %0 = load ptr, ptr %vfn + %call = tail call i32 %0(ptr %d), !prof !8 + ret i32 %call +} + +define i32 @_ZN5Base15func1Ev(ptr %this) { +entry: + ret i32 2 +} + +declare i32 @_ZN5Base25func2Ev(ptr) +declare i32 @_ZN5Base15func0Ev(ptr) +declare void @_ZN5Base35func3Ev(ptr) + +!0 = !{i64 16, !"_ZTS5Base1"} +!1 = !{i64 48, !"_ZTS5Base2"} +!2 = !{i64 16, !"_ZTS8Derived1"} +!3 = !{i64 64, !"_ZTS5Base1"} +!4 = !{i64 40, !"_ZTS5Base2"} +!5 = !{i64 16, !"_ZTS5Base3"} +!6 = !{i64 16, !"_ZTS8Derived2"} +!7 = !{!"VP", i32 2, i64 1600, i64 -9064381665493407289, i64 800, i64 5035968517245772950, i64 500, i64 3215870116411581797, i64 300} +!8 = !{!"VP", i32 0, i64 1600, i64 6804820478065511155, i64 1600})IR"); + + Function *F = M->getFunction("testfunc"); + CallInst *CI = dyn_cast(&*std::next(F->front().rbegin())); + ASSERT_TRUE(CI && CI->isIndirectCall()); + + // Create the constant and the branch weights + SmallVector VTableAddressPoints; + + for (auto &[VTableName, AddressPointOffset] : {std::pair{"_ZTV5Base1", 16}, + {"_ZTV8Derived1", 16}, + {"_ZTV8Derived2", 64}}) + VTableAddressPoints.push_back(getVTableAddressPointOffset( + M->getGlobalVariable(VTableName), AddressPointOffset)); + + MDBuilder MDB(C); + MDNode *BranchWeights = MDB.createBranchWeights(1600, 0); + + size_t OrigEntryBBSize = F->front().size(); + + LoadInst *VPtr = dyn_cast(&*F->front().begin()); + + Function *Callee = M->getFunction("_ZN5Base15func1Ev"); + // Tests that promoted direct call is returned. + CallBase &DirectCB = promoteCallWithVTableCmp( + *CI, VPtr, Callee, VTableAddressPoints, BranchWeights); + EXPECT_EQ(DirectCB.getCalledOperand(), Callee); + + // Promotion inserts 3 icmp instructions and 2 or instructions, and removes + // 1 call instruction from the entry block. + EXPECT_EQ(F->front().size(), OrigEntryBBSize + 4); +} -- GitLab From d102ee63e849cdaa586fd1aaae900c1399bf2b76 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Sun, 19 May 2024 16:51:07 -0700 Subject: [PATCH 043/793] [clang] Use operator==(StringRef, StringRef) (NFC) (#92708) --- clang-tools-extra/modularize/ModularizeUtilities.cpp | 6 ++---- clang/lib/Driver/ToolChains/Clang.cpp | 2 +- clang/utils/TableGen/ClangAttrEmitter.cpp | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/clang-tools-extra/modularize/ModularizeUtilities.cpp b/clang-tools-extra/modularize/ModularizeUtilities.cpp index 53e8a49d1a54..b202b3aae8f8 100644 --- a/clang-tools-extra/modularize/ModularizeUtilities.cpp +++ b/clang-tools-extra/modularize/ModularizeUtilities.cpp @@ -435,11 +435,9 @@ static std::string replaceDotDot(StringRef Path) { llvm::sys::path::const_iterator B = llvm::sys::path::begin(Path), E = llvm::sys::path::end(Path); while (B != E) { - if (B->compare(".") == 0) { - } - else if (B->compare("..") == 0) + if (*B == "..") llvm::sys::path::remove_filename(Buffer); - else + else if (*B != ".") llvm::sys::path::append(Buffer, *B); ++B; } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index c3e6d563f3bd..6d2015b2cd15 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1522,7 +1522,7 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, auto isPAuthLR = [](const char *member) { llvm::AArch64::ExtensionInfo pauthlr_extension = llvm::AArch64::getExtensionByID(llvm::AArch64::AEK_PAUTHLR); - return (pauthlr_extension.Feature.compare(member) == 0); + return pauthlr_extension.Feature == member; }; if (std::any_of(CmdArgs.begin(), CmdArgs.end(), isPAuthLR)) diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index aafbf1f40949..ca7630adfbb7 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -1845,7 +1845,7 @@ static LateAttrParseKind getLateAttrParseKind(const Record *Attr) { PrintFatalError(Attr, "Field `" + llvm::Twine(LateParsedStr) + "`should only have one super class"); - if (SuperClasses[0]->getName().compare(LateAttrParseKindStr) != 0) + if (SuperClasses[0]->getName() != LateAttrParseKindStr) PrintFatalError(Attr, "Field `" + llvm::Twine(LateParsedStr) + "`should only have type `" + llvm::Twine(LateAttrParseKindStr) + -- GitLab From 0bced10f290bb96d675874a89f1b6789a2384e30 Mon Sep 17 00:00:00 2001 From: Freddy Ye Date: Mon, 20 May 2024 08:53:21 +0800 Subject: [PATCH 044/793] [SDAG][X86] Extend SplitVecOp_VSETCC for STRICT_FSETCC. (#92509) --- .../SelectionDAG/LegalizeVectorTypes.cpp | 19 +++++++-- .../CodeGen/X86/vec-strict-cmp-512-skx.ll | 40 +++++++++++++++++++ 2 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 llvm/test/CodeGen/X86/vec-strict-cmp-512-skx.ll diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp index cd858003cf03..dca5a481fbd0 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -3033,6 +3033,7 @@ bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) { "operand!\n"); case ISD::VP_SETCC: + case ISD::STRICT_FSETCC: case ISD::SETCC: Res = SplitVecOp_VSETCC(N); break; case ISD::BITCAST: Res = SplitVecOp_BITCAST(N); break; case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break; @@ -3997,14 +3998,16 @@ SDValue DAGTypeLegalizer::SplitVecOp_TruncateHelper(SDNode *N) { } SDValue DAGTypeLegalizer::SplitVecOp_VSETCC(SDNode *N) { + bool isStrict = N->getOpcode() == ISD::STRICT_FSETCC; assert(N->getValueType(0).isVector() && - N->getOperand(0).getValueType().isVector() && + N->getOperand(isStrict ? 1 : 0).getValueType().isVector() && "Operand types must be vectors"); // The result has a legal vector type, but the input needs splitting. SDValue Lo0, Hi0, Lo1, Hi1, LoRes, HiRes; SDLoc DL(N); - GetSplitVector(N->getOperand(0), Lo0, Hi0); - GetSplitVector(N->getOperand(1), Lo1, Hi1); + GetSplitVector(N->getOperand(isStrict ? 1 : 0), Lo0, Hi0); + GetSplitVector(N->getOperand(isStrict ? 2 : 1), Lo1, Hi1); + auto PartEltCnt = Lo0.getValueType().getVectorElementCount(); LLVMContext &Context = *DAG.getContext(); @@ -4014,6 +4017,16 @@ SDValue DAGTypeLegalizer::SplitVecOp_VSETCC(SDNode *N) { if (N->getOpcode() == ISD::SETCC) { LoRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Lo0, Lo1, N->getOperand(2)); HiRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Hi0, Hi1, N->getOperand(2)); + } else if (N->getOpcode() == ISD::STRICT_FSETCC) { + LoRes = DAG.getNode(ISD::STRICT_FSETCC, DL, + DAG.getVTList(PartResVT, N->getValueType(1)), + N->getOperand(0), Lo0, Lo1, N->getOperand(3)); + HiRes = DAG.getNode(ISD::STRICT_FSETCC, DL, + DAG.getVTList(PartResVT, N->getValueType(1)), + N->getOperand(0), Hi0, Hi1, N->getOperand(3)); + SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, + LoRes.getValue(1), HiRes.getValue(1)); + ReplaceValueWith(SDValue(N, 1), NewChain); } else { assert(N->getOpcode() == ISD::VP_SETCC && "Expected VP_SETCC opcode"); SDValue MaskLo, MaskHi, EVLLo, EVLHi; diff --git a/llvm/test/CodeGen/X86/vec-strict-cmp-512-skx.ll b/llvm/test/CodeGen/X86/vec-strict-cmp-512-skx.ll new file mode 100644 index 000000000000..3028b7496737 --- /dev/null +++ b/llvm/test/CodeGen/X86/vec-strict-cmp-512-skx.ll @@ -0,0 +1,40 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64 -mcpu=skx | FileCheck %s --check-prefixes=SKX + +;; Test no crash for AVX512 targets without prefer-vector-width=512. + +define <16 x i32> @test_v16f32_oeq_q(<16 x i32> %a, <16 x i32> %b, <16 x float> %f1, <16 x float> %f2) #0 { +; SKX-LABEL: test_v16f32_oeq_q: +; SKX: # %bb.0: +; SKX-NEXT: vcmpeqps %ymm7, %ymm5, %k1 +; SKX-NEXT: vcmpeqps %ymm6, %ymm4, %k2 +; SKX-NEXT: vpblendmd %ymm0, %ymm2, %ymm0 {%k2} +; SKX-NEXT: vpblendmd %ymm1, %ymm3, %ymm1 {%k1} +; SKX-NEXT: retq + %cond = call <16 x i1> @llvm.experimental.constrained.fcmp.v16f32( + <16 x float> %f1, <16 x float> %f2, metadata !"oeq", + metadata !"fpexcept.strict") #0 + %res = select <16 x i1> %cond, <16 x i32> %a, <16 x i32> %b + ret <16 x i32> %res +} + +define <8 x i32> @test_v8f64_oeq_q(<8 x i32> %a, <8 x i32> %b, <8 x double> %f1, <8 x double> %f2) #0 { +; SKX-LABEL: test_v8f64_oeq_q: +; SKX: # %bb.0: +; SKX-NEXT: vcmpeqpd %ymm4, %ymm2, %k0 +; SKX-NEXT: vcmpeqpd %ymm5, %ymm3, %k1 +; SKX-NEXT: kshiftlb $4, %k1, %k1 +; SKX-NEXT: korb %k1, %k0, %k1 +; SKX-NEXT: vpblendmd %ymm0, %ymm1, %ymm0 {%k1} +; SKX-NEXT: retq + %cond = call <8 x i1> @llvm.experimental.constrained.fcmp.v8f64( + <8 x double> %f1, <8 x double> %f2, metadata !"oeq", + metadata !"fpexcept.strict") #0 + %res = select <8 x i1> %cond, <8 x i32> %a, <8 x i32> %b + ret <8 x i32> %res +} + +declare <16 x i1> @llvm.experimental.constrained.fcmp.v16f32(<16 x float>, <16 x float>, metadata, metadata) +declare <8 x i1> @llvm.experimental.constrained.fcmp.v8f64(<8 x double>, <8 x double>, metadata, metadata) + +attributes #0 = { nounwind strictfp "min-legal-vector-width"="0" } -- GitLab From 89d0937348ebd4b55f17d503910be9300aa44a13 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Sun, 19 May 2024 18:17:53 -0700 Subject: [PATCH 045/793] [llvm] Use StringRef::contains (NFC) (#92710) --- llvm/lib/IR/Mangler.cpp | 2 +- llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp | 2 +- llvm/lib/TextAPI/Utils.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/lib/IR/Mangler.cpp b/llvm/lib/IR/Mangler.cpp index 72e2bc1f24ac..019fe844e286 100644 --- a/llvm/lib/IR/Mangler.cpp +++ b/llvm/lib/IR/Mangler.cpp @@ -292,7 +292,7 @@ void llvm::emitLinkerFlagsForUsedCOFF(raw_ostream &OS, const GlobalValue *GV, std::optional llvm::getArm64ECMangledFunctionName(StringRef Name) { bool IsCppFn = Name[0] == '?'; - if (IsCppFn && Name.find("$$h") != std::string::npos) + if (IsCppFn && Name.contains("$$h")) return std::nullopt; if (!IsCppFn && Name[0] == '#') return std::nullopt; diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp index 32de8b9587b4..9fde26c900f5 100644 --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp @@ -1886,7 +1886,7 @@ static bool buildEnqueueKernel(const SPIRV::IncomingCall *Call, // Local sizes arguments: Sizes of block invoke arguments. Clang generates // local size operands as an array, so we need to unpack them. SmallVector LocalSizes; - if (Call->Builtin->Name.find("_varargs") != StringRef::npos || IsSpirvOp) { + if (Call->Builtin->Name.contains("_varargs") || IsSpirvOp) { const unsigned LocalSizeArrayIdx = HasEvents ? 9 : 6; Register GepReg = Call->Arguments[LocalSizeArrayIdx]; MachineInstr *GepMI = MRI->getUniqueVRegDef(GepReg); diff --git a/llvm/lib/TextAPI/Utils.cpp b/llvm/lib/TextAPI/Utils.cpp index 08f14f65177e..01021e3a264d 100644 --- a/llvm/lib/TextAPI/Utils.cpp +++ b/llvm/lib/TextAPI/Utils.cpp @@ -184,7 +184,7 @@ llvm::Expected llvm::MachO::createRegexFromGlob(StringRef Glob) { break; } default: - if (RegexMetachars.find(C) != StringRef::npos) + if (RegexMetachars.contains(C)) RegexString.push_back('\\'); RegexString.push_back(C); } -- GitLab From fc0144a30cf20d6405411da141d11bfde143d3d2 Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Mon, 20 May 2024 10:36:03 +0800 Subject: [PATCH 046/793] [Serialization] Read the initializer for interesting static variables before consuming it (#92353) Close https://github.com/llvm/llvm-project/issues/91418 Since we load the variable's initializers lazily, it'd be problematic if the initializers dependent on each other. So here we try to load the initializers of static variables to make sure they are passed to code generator by order. If we read any thing interesting, we would consume that before emitting the current declaration. --- clang/lib/Serialization/ASTReaderDecl.cpp | 29 ++- clang/test/Modules/pr91418.cppm | 65 +++++ clang/test/OpenMP/nvptx_lambda_capturing.cpp | 246 +++++++++---------- 3 files changed, 214 insertions(+), 126 deletions(-) create mode 100644 clang/test/Modules/pr91418.cppm diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 0c647086e304..a6254b70560c 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -4186,12 +4186,35 @@ void ASTReader::PassInterestingDeclsToConsumer() { GetDecl(ID); EagerlyDeserializedDecls.clear(); - while (!PotentiallyInterestingDecls.empty()) { - Decl *D = PotentiallyInterestingDecls.front(); - PotentiallyInterestingDecls.pop_front(); + auto ConsumingPotentialInterestingDecls = [this]() { + while (!PotentiallyInterestingDecls.empty()) { + Decl *D = PotentiallyInterestingDecls.front(); + PotentiallyInterestingDecls.pop_front(); + if (isConsumerInterestedIn(D)) + PassInterestingDeclToConsumer(D); + } + }; + std::deque MaybeInterestingDecls = + std::move(PotentiallyInterestingDecls); + assert(PotentiallyInterestingDecls.empty()); + while (!MaybeInterestingDecls.empty()) { + Decl *D = MaybeInterestingDecls.front(); + MaybeInterestingDecls.pop_front(); + // Since we load the variable's initializers lazily, it'd be problematic + // if the initializers dependent on each other. So here we try to load the + // initializers of static variables to make sure they are passed to code + // generator by order. If we read anything interesting, we would consume + // that before emitting the current declaration. + if (auto *VD = dyn_cast(D); + VD && VD->isFileVarDecl() && !VD->isExternallyVisible()) + VD->getInit(); + ConsumingPotentialInterestingDecls(); if (isConsumerInterestedIn(D)) PassInterestingDeclToConsumer(D); } + + // If we add any new potential interesting decl in the last call, consume it. + ConsumingPotentialInterestingDecls(); } void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { diff --git a/clang/test/Modules/pr91418.cppm b/clang/test/Modules/pr91418.cppm new file mode 100644 index 000000000000..b507df162643 --- /dev/null +++ b/clang/test/Modules/pr91418.cppm @@ -0,0 +1,65 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -x c++-header %t/foo.h \ +// RUN: -emit-pch -o %t/foo.pch +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/use.cpp -include-pch \ +// RUN: %t/foo.pch -emit-llvm -o - | FileCheck %t/use.cpp + +//--- foo.h +#ifndef FOO_H +#define FOO_H +typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16))); + +static __inline__ __m128 __attribute__((__always_inline__, __min_vector_width__(128))) +_mm_setr_ps(float __z, float __y, float __x, float __w) +{ + return __extension__ (__m128){ __z, __y, __x, __w }; +} + +typedef __m128 VR; + +inline VR MakeVR( float X, float Y, float Z, float W ) +{ + return _mm_setr_ps( X, Y, Z, W ); +} + +extern "C" float sqrtf(float); + +namespace VectorSinConstantsSSE +{ + float a = (16 * sqrtf(0.225f)); + VR A = MakeVR(a, a, a, a); + static const float b = (16 * sqrtf(0.225f)); + static const VR B = MakeVR(b, b, b, b); +} + +#endif // FOO_H + +//--- use.cpp +#include "foo.h" +float use() { + return VectorSinConstantsSSE::A[0] + VectorSinConstantsSSE::A[1] + + VectorSinConstantsSSE::A[2] + VectorSinConstantsSSE::A[3] + + VectorSinConstantsSSE::B[0] + VectorSinConstantsSSE::B[1] + + VectorSinConstantsSSE::B[2] + VectorSinConstantsSSE::B[3]; +} + +// CHECK: define{{.*}}@__cxx_global_var_init( +// CHECK: store{{.*}}, ptr @_ZN21VectorSinConstantsSSE1aE + +// CHECK: define{{.*}}@__cxx_global_var_init.1( +// CHECK: store{{.*}}, ptr @_ZN21VectorSinConstantsSSE1AE + +// CHECK: define{{.*}}@__cxx_global_var_init.2( +// CHECK: store{{.*}}, ptr @_ZN21VectorSinConstantsSSEL1BE + +// CHECK: define{{.*}}@__cxx_global_var_init.3( +// CHECK: store{{.*}}, ptr @_ZN21VectorSinConstantsSSEL1bE + +// CHECK: @_GLOBAL__sub_I_use.cpp +// CHECK: call{{.*}}@__cxx_global_var_init( +// CHECK: call{{.*}}@__cxx_global_var_init.1( +// CHECK: call{{.*}}@__cxx_global_var_init.3( +// CHECK: call{{.*}}@__cxx_global_var_init.2( diff --git a/clang/test/OpenMP/nvptx_lambda_capturing.cpp b/clang/test/OpenMP/nvptx_lambda_capturing.cpp index 641fbc38dd6b..efea8d4a0561 100644 --- a/clang/test/OpenMP/nvptx_lambda_capturing.cpp +++ b/clang/test/OpenMP/nvptx_lambda_capturing.cpp @@ -1165,8 +1165,113 @@ int main(int argc, char **argv) { // CHECK2-NEXT: ret void // // +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l27 +// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[L:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK3-NEXT: entry: +// CHECK3-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[L_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[L1:%.*]] = alloca [[CLASS_ANON:%.*]], align 8 +// CHECK3-NEXT: [[_TMP2:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR]], align 8 +// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK3-NEXT: store ptr [[L]], ptr [[L_ADDR]], align 8 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[L_ADDR]], align 8 +// CHECK3-NEXT: store ptr [[TMP1]], ptr [[TMP]], align 8 +// CHECK3-NEXT: [[TMP2:%.*]] = call i32 @__kmpc_target_init(ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l27_kernel_environment, ptr [[DYN_PTR]]) +// CHECK3-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP2]], -1 +// CHECK3-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]] +// CHECK3: user_code.entry: +// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[L1]], ptr align 8 [[TMP3]], i64 8, i1 false) +// CHECK3-NEXT: store ptr [[L1]], ptr [[_TMP2]], align 8 +// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[_TMP2]], align 8 +// CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP4]], i32 0, i32 0 +// CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 +// CHECK3-NEXT: [[TMP6:%.*]] = load ptr, ptr [[_TMP2]], align 8 +// CHECK3-NEXT: [[CALL:%.*]] = call noundef i32 @_ZZN1S3fooEvENKUlvE_clEv(ptr noundef nonnull align 8 dereferenceable(8) [[TMP6]]) #[[ATTR7:[0-9]+]] +// CHECK3-NEXT: call void @__kmpc_target_deinit() +// CHECK3-NEXT: ret void +// CHECK3: worker.exit: +// CHECK3-NEXT: ret void +// +// +// CHECK3-LABEL: define {{[^@]+}}@_ZZN1S3fooEvENKUlvE_clEv +// CHECK3-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) #[[ATTR2:[0-9]+]] comdat align 2 { +// CHECK3-NEXT: entry: +// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[CLASS_ANON:%.*]], ptr [[THIS1]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK3-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP2:%.*]] = load i32, ptr [[A]], align 4 +// CHECK3-NEXT: ret i32 [[TMP2]] +// +// +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l29 +// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[L:%.*]]) #[[ATTR3:[0-9]+]] { +// CHECK3-NEXT: entry: +// CHECK3-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[L_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[CAPTURED_VARS_ADDRS:%.*]] = alloca [2 x ptr], align 8 +// CHECK3-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR]], align 8 +// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK3-NEXT: store ptr [[L]], ptr [[L_ADDR]], align 8 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[L_ADDR]], align 8 +// CHECK3-NEXT: store ptr [[TMP1]], ptr [[TMP]], align 8 +// CHECK3-NEXT: [[TMP2:%.*]] = call i32 @__kmpc_target_init(ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l29_kernel_environment, ptr [[DYN_PTR]]) +// CHECK3-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP2]], -1 +// CHECK3-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]] +// CHECK3: user_code.entry: +// CHECK3-NEXT: [[TMP3:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]]) +// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[CAPTURED_VARS_ADDRS]], i64 0, i64 0 +// CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 +// CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[CAPTURED_VARS_ADDRS]], i64 0, i64 1 +// CHECK3-NEXT: store ptr [[TMP4]], ptr [[TMP6]], align 8 +// CHECK3-NEXT: call void @__kmpc_parallel_51(ptr @[[GLOB1]], i32 [[TMP3]], i32 1, i32 -1, i32 -1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l29_omp_outlined, ptr null, ptr [[CAPTURED_VARS_ADDRS]], i64 2) +// CHECK3-NEXT: call void @__kmpc_target_deinit() +// CHECK3-NEXT: ret void +// CHECK3: worker.exit: +// CHECK3-NEXT: ret void +// +// +// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l29_omp_outlined +// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[L:%.*]]) #[[ATTR4:[0-9]+]] { +// CHECK3-NEXT: entry: +// CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[L_ADDR:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: [[L1:%.*]] = alloca [[CLASS_ANON:%.*]], align 8 +// CHECK3-NEXT: [[_TMP2:%.*]] = alloca ptr, align 8 +// CHECK3-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 +// CHECK3-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 +// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK3-NEXT: store ptr [[L]], ptr [[L_ADDR]], align 8 +// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[L_ADDR]], align 8 +// CHECK3-NEXT: store ptr [[TMP1]], ptr [[TMP]], align 8 +// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[L1]], ptr align 8 [[TMP2]], i64 8, i1 false) +// CHECK3-NEXT: store ptr [[L1]], ptr [[_TMP2]], align 8 +// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[_TMP2]], align 8 +// CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP3]], i32 0, i32 0 +// CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8 +// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[_TMP2]], align 8 +// CHECK3-NEXT: [[CALL:%.*]] = call noundef i32 @_ZZN1S3fooEvENKUlvE_clEv(ptr noundef nonnull align 8 dereferenceable(8) [[TMP5]]) #[[ATTR7]] +// CHECK3-NEXT: ret void +// +// // CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l41 -// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], i64 noundef [[ARGC:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[B:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]], ptr noundef [[D:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[A:%.*]], ptr noundef nonnull align 8 dereferenceable(40) [[L:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], i64 noundef [[ARGC:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[B:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]], ptr noundef [[D:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[A:%.*]], ptr noundef nonnull align 8 dereferenceable(40) [[L:%.*]]) #[[ATTR0]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[ARGC_ADDR:%.*]] = alloca i64, align 8 @@ -1178,7 +1283,7 @@ int main(int argc, char **argv) { // CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[_TMP1:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[_TMP2:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[L3:%.*]] = alloca [[CLASS_ANON:%.*]], align 8 +// CHECK3-NEXT: [[L3:%.*]] = alloca [[CLASS_ANON_1:%.*]], align 8 // CHECK3-NEXT: [[_TMP4:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[B5:%.*]] = alloca i32, align 4 // CHECK3-NEXT: [[_TMP6:%.*]] = alloca ptr, align 8 @@ -1214,20 +1319,20 @@ int main(int argc, char **argv) { // CHECK3-NEXT: store i32 [[TMP9]], ptr [[C7]], align 4 // CHECK3-NEXT: store ptr [[C7]], ptr [[_TMP8]], align 8 // CHECK3-NEXT: [[TMP10:%.*]] = load ptr, ptr [[_TMP4]], align 8 -// CHECK3-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP10]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP10]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[ARGC_ADDR]], ptr [[TMP11]], align 8 -// CHECK3-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP10]], i32 0, i32 1 +// CHECK3-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP10]], i32 0, i32 1 // CHECK3-NEXT: [[TMP13:%.*]] = load ptr, ptr [[_TMP6]], align 8 // CHECK3-NEXT: store ptr [[TMP13]], ptr [[TMP12]], align 8 -// CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP10]], i32 0, i32 2 +// CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP10]], i32 0, i32 2 // CHECK3-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP8]], align 8 // CHECK3-NEXT: store ptr [[TMP15]], ptr [[TMP14]], align 8 -// CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP10]], i32 0, i32 3 +// CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP10]], i32 0, i32 3 // CHECK3-NEXT: store ptr [[D_ADDR]], ptr [[TMP16]], align 8 -// CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP10]], i32 0, i32 4 +// CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP10]], i32 0, i32 4 // CHECK3-NEXT: store ptr [[TMP2]], ptr [[TMP17]], align 8 // CHECK3-NEXT: [[TMP18:%.*]] = load ptr, ptr [[_TMP4]], align 8 -// CHECK3-NEXT: [[CALL:%.*]] = call noundef i64 @"_ZZ4mainENK3$_0clEv"(ptr noundef nonnull align 8 dereferenceable(40) [[TMP18]]) #[[ATTR7:[0-9]+]] +// CHECK3-NEXT: [[CALL:%.*]] = call noundef i64 @"_ZZ4mainENK3$_0clEv"(ptr noundef nonnull align 8 dereferenceable(40) [[TMP18]]) #[[ATTR7]] // CHECK3-NEXT: call void @__kmpc_target_deinit() // CHECK3-NEXT: ret void // CHECK3: worker.exit: @@ -1235,7 +1340,7 @@ int main(int argc, char **argv) { // // // CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l43 -// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[ARGC:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[B:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]], ptr noundef [[D:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[A:%.*]], ptr noundef nonnull align 8 dereferenceable(40) [[L:%.*]]) #[[ATTR3:[0-9]+]] { +// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[ARGC:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[B:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]], ptr noundef [[D:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[A:%.*]], ptr noundef nonnull align 8 dereferenceable(40) [[L:%.*]]) #[[ATTR3]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[ARGC_ADDR:%.*]] = alloca ptr, align 8 @@ -1267,7 +1372,7 @@ int main(int argc, char **argv) { // CHECK3-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP5]], -1 // CHECK3-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]] // CHECK3: user_code.entry: -// CHECK3-NEXT: [[TMP6:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]]) +// CHECK3-NEXT: [[TMP6:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) // CHECK3-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP]], align 8 // CHECK3-NEXT: [[TMP8:%.*]] = load ptr, ptr [[_TMP1]], align 8 // CHECK3-NEXT: [[TMP9:%.*]] = load ptr, ptr [[D_ADDR]], align 8 @@ -1292,7 +1397,7 @@ int main(int argc, char **argv) { // // // CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l43_omp_outlined -// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[ARGC:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[B:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]], ptr noundef [[D:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[A:%.*]], ptr noundef nonnull align 8 dereferenceable(40) [[L:%.*]]) #[[ATTR4:[0-9]+]] { +// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[ARGC:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[B:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[C:%.*]], ptr noundef [[D:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[A:%.*]], ptr noundef nonnull align 8 dereferenceable(40) [[L:%.*]]) #[[ATTR4]] { // CHECK3-NEXT: entry: // CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 @@ -1305,7 +1410,7 @@ int main(int argc, char **argv) { // CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[_TMP1:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[_TMP2:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[L3:%.*]] = alloca [[CLASS_ANON:%.*]], align 8 +// CHECK3-NEXT: [[L3:%.*]] = alloca [[CLASS_ANON_1:%.*]], align 8 // CHECK3-NEXT: [[_TMP4:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[ARGC5:%.*]] = alloca i32, align 4 // CHECK3-NEXT: [[B6:%.*]] = alloca i32, align 4 @@ -1345,128 +1450,23 @@ int main(int argc, char **argv) { // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP3]], align 4 // CHECK3-NEXT: store i32 [[TMP11]], ptr [[A10]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = load ptr, ptr [[_TMP4]], align 8 -// CHECK3-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP12]], i32 0, i32 0 +// CHECK3-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP12]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[ARGC5]], ptr [[TMP13]], align 8 -// CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP12]], i32 0, i32 1 +// CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP12]], i32 0, i32 1 // CHECK3-NEXT: [[TMP15:%.*]] = load ptr, ptr [[_TMP7]], align 8 // CHECK3-NEXT: store ptr [[TMP15]], ptr [[TMP14]], align 8 -// CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP12]], i32 0, i32 2 +// CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP12]], i32 0, i32 2 // CHECK3-NEXT: [[TMP17:%.*]] = load ptr, ptr [[_TMP9]], align 8 // CHECK3-NEXT: store ptr [[TMP17]], ptr [[TMP16]], align 8 -// CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP12]], i32 0, i32 3 +// CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP12]], i32 0, i32 3 // CHECK3-NEXT: store ptr [[D_ADDR]], ptr [[TMP18]], align 8 -// CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[CLASS_ANON]], ptr [[TMP12]], i32 0, i32 4 +// CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP12]], i32 0, i32 4 // CHECK3-NEXT: store ptr [[A10]], ptr [[TMP19]], align 8 // CHECK3-NEXT: [[TMP20:%.*]] = load ptr, ptr [[_TMP4]], align 8 // CHECK3-NEXT: [[CALL:%.*]] = call noundef i64 @"_ZZ4mainENK3$_0clEv"(ptr noundef nonnull align 8 dereferenceable(40) [[TMP20]]) #[[ATTR7]] // CHECK3-NEXT: ret void // // -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l27 -// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[L:%.*]]) #[[ATTR0]] { -// CHECK3-NEXT: entry: -// CHECK3-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[L_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[L1:%.*]] = alloca [[CLASS_ANON_1:%.*]], align 8 -// CHECK3-NEXT: [[_TMP2:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR]], align 8 -// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 -// CHECK3-NEXT: store ptr [[L]], ptr [[L_ADDR]], align 8 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[L_ADDR]], align 8 -// CHECK3-NEXT: store ptr [[TMP1]], ptr [[TMP]], align 8 -// CHECK3-NEXT: [[TMP2:%.*]] = call i32 @__kmpc_target_init(ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l27_kernel_environment, ptr [[DYN_PTR]]) -// CHECK3-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP2]], -1 -// CHECK3-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]] -// CHECK3: user_code.entry: -// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8 -// CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[L1]], ptr align 8 [[TMP3]], i64 8, i1 false) -// CHECK3-NEXT: store ptr [[L1]], ptr [[_TMP2]], align 8 -// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[_TMP2]], align 8 -// CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP4]], i32 0, i32 0 -// CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 -// CHECK3-NEXT: [[TMP6:%.*]] = load ptr, ptr [[_TMP2]], align 8 -// CHECK3-NEXT: [[CALL:%.*]] = call noundef i32 @_ZZN1S3fooEvENKUlvE_clEv(ptr noundef nonnull align 8 dereferenceable(8) [[TMP6]]) #[[ATTR7]] -// CHECK3-NEXT: call void @__kmpc_target_deinit() -// CHECK3-NEXT: ret void -// CHECK3: worker.exit: -// CHECK3-NEXT: ret void -// -// -// CHECK3-LABEL: define {{[^@]+}}@_ZZN1S3fooEvENKUlvE_clEv -// CHECK3-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) #[[ATTR2:[0-9]+]] comdat align 2 { -// CHECK3-NEXT: entry: -// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 -// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[CLASS_ANON_1:%.*]], ptr [[THIS1]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8 -// CHECK3-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 0 -// CHECK3-NEXT: [[TMP2:%.*]] = load i32, ptr [[A]], align 4 -// CHECK3-NEXT: ret i32 [[TMP2]] -// -// -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l29 -// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[L:%.*]]) #[[ATTR3]] { -// CHECK3-NEXT: entry: -// CHECK3-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[L_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[CAPTURED_VARS_ADDRS:%.*]] = alloca [2 x ptr], align 8 -// CHECK3-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR]], align 8 -// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 -// CHECK3-NEXT: store ptr [[L]], ptr [[L_ADDR]], align 8 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[L_ADDR]], align 8 -// CHECK3-NEXT: store ptr [[TMP1]], ptr [[TMP]], align 8 -// CHECK3-NEXT: [[TMP2:%.*]] = call i32 @__kmpc_target_init(ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l29_kernel_environment, ptr [[DYN_PTR]]) -// CHECK3-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP2]], -1 -// CHECK3-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]] -// CHECK3: user_code.entry: -// CHECK3-NEXT: [[TMP3:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) -// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP]], align 8 -// CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[CAPTURED_VARS_ADDRS]], i64 0, i64 0 -// CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP5]], align 8 -// CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[CAPTURED_VARS_ADDRS]], i64 0, i64 1 -// CHECK3-NEXT: store ptr [[TMP4]], ptr [[TMP6]], align 8 -// CHECK3-NEXT: call void @__kmpc_parallel_51(ptr @[[GLOB1]], i32 [[TMP3]], i32 1, i32 -1, i32 -1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l29_omp_outlined, ptr null, ptr [[CAPTURED_VARS_ADDRS]], i64 2) -// CHECK3-NEXT: call void @__kmpc_target_deinit() -// CHECK3-NEXT: ret void -// CHECK3: worker.exit: -// CHECK3-NEXT: ret void -// -// -// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__ZN1S3fooEv_l29_omp_outlined -// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef [[THIS:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[L:%.*]]) #[[ATTR4]] { -// CHECK3-NEXT: entry: -// CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[L_ADDR:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[L1:%.*]] = alloca [[CLASS_ANON_1:%.*]], align 8 -// CHECK3-NEXT: [[_TMP2:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 -// CHECK3-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 -// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 -// CHECK3-NEXT: store ptr [[L]], ptr [[L_ADDR]], align 8 -// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK3-NEXT: [[TMP1:%.*]] = load ptr, ptr [[L_ADDR]], align 8 -// CHECK3-NEXT: store ptr [[TMP1]], ptr [[TMP]], align 8 -// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP]], align 8 -// CHECK3-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[L1]], ptr align 8 [[TMP2]], i64 8, i1 false) -// CHECK3-NEXT: store ptr [[L1]], ptr [[_TMP2]], align 8 -// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[_TMP2]], align 8 -// CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[CLASS_ANON_1]], ptr [[TMP3]], i32 0, i32 0 -// CHECK3-NEXT: store ptr [[TMP0]], ptr [[TMP4]], align 8 -// CHECK3-NEXT: [[TMP5:%.*]] = load ptr, ptr [[_TMP2]], align 8 -// CHECK3-NEXT: [[CALL:%.*]] = call noundef i32 @_ZZN1S3fooEvENKUlvE_clEv(ptr noundef nonnull align 8 dereferenceable(8) [[TMP5]]) #[[ATTR7]] -// CHECK3-NEXT: ret void -// -// // CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooIZN1S3fooEvEUlvE_EiRKT__l18 // CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef nonnull align 8 dereferenceable(8) [[T:%.*]]) #[[ATTR3]] { // CHECK3-NEXT: entry: @@ -1500,7 +1500,7 @@ int main(int argc, char **argv) { // CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[T_ADDR:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: [[TMP:%.*]] = alloca ptr, align 8 -// CHECK3-NEXT: [[T1:%.*]] = alloca [[CLASS_ANON_1:%.*]], align 8 +// CHECK3-NEXT: [[T1:%.*]] = alloca [[CLASS_ANON:%.*]], align 8 // CHECK3-NEXT: [[_TMP2:%.*]] = alloca ptr, align 8 // CHECK3-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK3-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8 -- GitLab From 91423d71938d7a1dba27188e6d854148a750a3dd Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Sun, 19 May 2024 20:15:31 -0700 Subject: [PATCH 047/793] [BOLT][NFC] Don't assign YAML profile to functions with no CFG (#92487) YAML profile for non-simple functions without CFG is 1) useless for optimizations, 2) can't be attached, similar to fdata profile, 3) would be reported as invalid/stale even if the profile is valid. Don't attempt to attach the profile in this case, aligning the behavior to DataReader. Test Plan: added yaml-non-simple.test --- bolt/lib/Profile/YAMLProfileReader.cpp | 3 ++ bolt/test/X86/yaml-non-simple.test | 71 ++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 bolt/test/X86/yaml-non-simple.test diff --git a/bolt/lib/Profile/YAMLProfileReader.cpp b/bolt/lib/Profile/YAMLProfileReader.cpp index 978a7cadfe79..29d94067f459 100644 --- a/bolt/lib/Profile/YAMLProfileReader.cpp +++ b/bolt/lib/Profile/YAMLProfileReader.cpp @@ -99,6 +99,9 @@ bool YAMLProfileReader::parseFunctionProfile( FuncRawBranchCount += YamlSI.Count; BF.setRawBranchCount(FuncRawBranchCount); + if (BF.empty()) + return true; + if (!opts::IgnoreHash && YamlBF.Hash != BF.computeHash(IsDFSOrder, HashFunction)) { if (opts::Verbosity >= 1) diff --git a/bolt/test/X86/yaml-non-simple.test b/bolt/test/X86/yaml-non-simple.test new file mode 100644 index 000000000000..fef98f692a71 --- /dev/null +++ b/bolt/test/X86/yaml-non-simple.test @@ -0,0 +1,71 @@ +## Check that YAML profile for non-simple function is not reported as stale. + +# RUN: split-file %s %t +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %t/main.s -o %t.o +# RUN: %clang %cflags %t.o -o %t.exe -nostdlib +# RUN: llvm-bolt %t.exe -o %t.out --data %t/yaml --profile-ignore-hash -v=1 \ +# RUN: --report-stale 2>&1 | FileCheck %s + +# CHECK: BOLT-INFO: could not disassemble function main. Will ignore. +# CHECK: BOLT-INFO: could not disassemble function main.cold. Will ignore. +# CHECK: BOLT-INFO: 0 out of 2 functions in the binary (0.0%) have non-empty execution profile +# CHECK: BOLT-INFO: 1 function with profile could not be optimized + +#--- main.s +.globl main +.type main, @function +main: + .cfi_startproc +.LBB00: + pushq %rbp + movq %rsp, %rbp + subq $16, %rsp + testq %rax, %rax + js .LBB03 +.LBB01: + jne .LBB04 +.LBB02: + nop +.LBB03: + xorl %eax, %eax + addq $16, %rsp + popq %rbp + retq +.LBB04: + xorl %eax, %eax + addq $16, %rsp + popq %rbp + retq + .cfi_endproc + .size main, .-main + +.globl main.cold +.type main.cold, @function +main.cold: + .cfi_startproc + nop + .cfi_endproc + .size main.cold, .-main.cold + +#--- yaml +--- +header: + profile-version: 1 + binary-name: 'yaml-non-simple.s.tmp.exe' + binary-build-id: '' + profile-flags: [ lbr ] + profile-origin: branch profile reader + profile-events: '' + dfs-order: false + hash-func: xxh3 +functions: + - name: main + fid: 0 + hash: 0x0000000000000000 + exec: 1 + nblocks: 5 + blocks: + - bid: 1 + insns: 1 + succ: [ { bid: 3, cnt: 1} ] +... -- GitLab From 6bf1601a0d9a01fe663442096466d46800483e0c Mon Sep 17 00:00:00 2001 From: Monad Date: Mon, 20 May 2024 12:20:47 +0800 Subject: [PATCH 048/793] [InstCombine] Fold pointer adding in integer to arithmetic add (#91596) Fold ``` llvm define i32 @src(i32 %x, i32 %y) { %base = inttoptr i32 %x to ptr %ptr = getelementptr inbounds i8, ptr %base, i32 %y %r = ptrtoint ptr %ptr to i32 ret i32 %r } ``` where both `%base` and `%ptr` have only one use, to ``` llvm define i32 @tgt(i32 %x, i32 %y) { %r = add i32 %x, %y ret i32 %r } ``` The `add` can be `nuw` if the GEP is `inbounds` and the offset is non-negative. The relevant Alive2 proof is https://alive2.llvm.org/ce/z/nP3RWy. ### Motivation It seems unnecessary to convert `int` to `ptr` just to get its offset. In most cases, they generates the same assembly, but sometimes it may miss some optimizations since the analysis of `GEP` is not as perfect as that of arithmetic operation. One example is https://github.com/dtcxzyw/llvm-opt-benchmark/blob/e3c822bf41df3a88ca38eba884a52b0cc7e70bf2/bench/protobuf/optimized/generated_message_reflection.cc.ll#L39860-L39873 ``` llvm %conv.i188 = zext i32 %145 to i64 %add.i189 = add i64 %conv.i188, %125 %146 = load i16, ptr %num_aux_entries10.i, align 2 %conv2.i191 = zext i16 %146 to i64 %mul.i192 = shl nuw nsw i64 %conv2.i191, 3 %add3.i193 = add i64 %add.i189, %mul.i192 %147 = inttoptr i64 %add3.i193 to ptr %sub.ptr.lhs.cast.i195 = ptrtoint ptr %144 to i64 %sub.ptr.rhs.cast.i196 = ptrtoint ptr %143 to i64 %sub.ptr.sub.i197 = sub i64 %sub.ptr.lhs.cast.i195, %sub.ptr.rhs.cast.i196 %add.ptr = getelementptr inbounds i8, ptr %147, i64 %sub.ptr.sub.i197 %sub.ptr.lhs.cast = ptrtoint ptr %add.ptr to i64 %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %125 ``` where `%conv.i188` first adds `%125` and then subtracts `%125` (the result is `%sub.ptr.sub`), which can be optimized. --- .../InstCombine/InstCombineCasts.cpp | 20 ++- llvm/test/Transforms/InstCombine/cast_ptr.ll | 151 ++++++++++++++++++ 2 files changed, 167 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index 11e31877de38..1b4c319032ca 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -2049,16 +2049,28 @@ Instruction *InstCombinerImpl::visitPtrToInt(PtrToIntInst &CI) { Mask->getType() == Ty) return BinaryOperator::CreateAnd(Builder.CreatePtrToInt(Ptr, Ty), Mask); - if (auto *GEP = dyn_cast(SrcOp)) { + if (auto *GEP = dyn_cast(SrcOp)) { // Fold ptrtoint(gep null, x) to multiply + constant if the GEP has one use. // While this can increase the number of instructions it doesn't actually // increase the overall complexity since the arithmetic is just part of // the GEP otherwise. if (GEP->hasOneUse() && isa(GEP->getPointerOperand())) { - return replaceInstUsesWith( - CI, Builder.CreateIntCast(EmitGEPOffset(cast(GEP)), Ty, - /*isSigned=*/false)); + return replaceInstUsesWith(CI, + Builder.CreateIntCast(EmitGEPOffset(GEP), Ty, + /*isSigned=*/false)); + } + + // (ptrtoint (gep (inttoptr Base), ...)) -> Base + Offset + Value *Base; + if (GEP->hasOneUse() && + match(GEP->getPointerOperand(), m_OneUse(m_IntToPtr(m_Value(Base)))) && + Base->getType() == Ty) { + Value *Offset = EmitGEPOffset(GEP); + auto *NewOp = BinaryOperator::CreateAdd(Base, Offset); + if (GEP->isInBounds() && isKnownNonNegative(Offset, SQ)) + NewOp->setHasNoUnsignedWrap(true); + return NewOp; } } diff --git a/llvm/test/Transforms/InstCombine/cast_ptr.ll b/llvm/test/Transforms/InstCombine/cast_ptr.ll index 5c6c012064e0..786ea876ddea 100644 --- a/llvm/test/Transforms/InstCombine/cast_ptr.ll +++ b/llvm/test/Transforms/InstCombine/cast_ptr.ll @@ -244,3 +244,154 @@ define <2 x i32> @insertelt_extra_use2(<2 x i32> %x, ptr %p) { %r = ptrtoint <2 x ptr> %i to <2 x i32> ret <2 x i32> %r } + +define i32 @ptr_add_in_int(i32 %x, i32 %y) { +; CHECK-LABEL: @ptr_add_in_int( +; CHECK-NEXT: [[R:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %ptr = inttoptr i32 %x to ptr + %p2 = getelementptr inbounds i8, ptr %ptr, i32 %y + %r = ptrtoint ptr %p2 to i32 + ret i32 %r +} + +define i32 @ptr_add_in_int_2(i32 %x, i32 %y) { +; CHECK-LABEL: @ptr_add_in_int_2( +; CHECK-NEXT: [[P2_IDX:%.*]] = shl nsw i32 [[Y:%.*]], 2 +; CHECK-NEXT: [[R:%.*]] = add i32 [[P2_IDX]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %ptr = inttoptr i32 %x to ptr + %p2 = getelementptr inbounds i32, ptr %ptr, i32 %y + %r = ptrtoint ptr %p2 to i32 + ret i32 %r +} + +define i32 @ptr_add_in_int_nneg(i32 %x, i32 %y) { +; CHECK-LABEL: @ptr_add_in_int_nneg( +; CHECK-NEXT: [[Z:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true) +; CHECK-NEXT: [[R:%.*]] = add nuw i32 [[Z]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %z = call i32 @llvm.abs.i32(i32 %y, i1 true) + %ptr = inttoptr i32 %x to ptr + %p2 = getelementptr inbounds i8, ptr %ptr, i32 %z + %r = ptrtoint ptr %p2 to i32 + ret i32 %r +} + +define i64 @ptr_add_in_int_different_type_1(i32 %x, i32 %y) { +; CHECK-LABEL: @ptr_add_in_int_different_type_1( +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = zext i32 [[TMP1]] to i64 +; CHECK-NEXT: ret i64 [[R]] +; + %ptr = inttoptr i32 %x to ptr + %p2 = getelementptr i8, ptr %ptr, i32 %y + %r = ptrtoint ptr %p2 to i64 + ret i64 %r +} + +define i16 @ptr_add_in_int_different_type_2(i32 %x, i32 %y) { +; CHECK-LABEL: @ptr_add_in_int_different_type_2( +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = trunc i32 [[TMP1]] to i16 +; CHECK-NEXT: ret i16 [[R]] +; + %ptr = inttoptr i32 %x to ptr + %p2 = getelementptr i8, ptr %ptr, i32 %y + %r = ptrtoint ptr %p2 to i16 + ret i16 %r +} + +define i32 @ptr_add_in_int_different_type_3(i16 %x, i32 %y) { +; CHECK-LABEL: @ptr_add_in_int_different_type_3( +; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[X:%.*]] to i32 +; CHECK-NEXT: [[R:%.*]] = add i32 [[TMP1]], [[Y:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %ptr = inttoptr i16 %x to ptr + %p2 = getelementptr i8, ptr %ptr, i32 %y + %r = ptrtoint ptr %p2 to i32 + ret i32 %r +} + +define i32 @ptr_add_in_int_different_type_4(i64 %x, i32 %y) { +; CHECK-LABEL: @ptr_add_in_int_different_type_4( +; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i32 +; CHECK-NEXT: [[R:%.*]] = add i32 [[TMP1]], [[Y:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %ptr = inttoptr i64 %x to ptr + %p2 = getelementptr i8, ptr %ptr, i32 %y + %r = ptrtoint ptr %p2 to i32 + ret i32 %r +} + +define i32 @ptr_add_in_int_not_inbounds(i32 %x, i32 %y) { +; CHECK-LABEL: @ptr_add_in_int_not_inbounds( +; CHECK-NEXT: [[Z:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true) +; CHECK-NEXT: [[R:%.*]] = add i32 [[Z]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[R]] +; + %z = call i32 @llvm.abs.i32(i32 %y, i1 true) + %ptr = inttoptr i32 %x to ptr + %p2 = getelementptr i8, ptr %ptr, i32 %z + %r = ptrtoint ptr %p2 to i32 + ret i32 %r +} + +define i32 @ptr_add_in_int_const(i32 %x) { +; CHECK-LABEL: @ptr_add_in_int_const( +; CHECK-NEXT: [[R:%.*]] = add nuw i32 [[X:%.*]], 4096 +; CHECK-NEXT: ret i32 [[R]] +; + %ptr = inttoptr i32 %x to ptr + %p2 = getelementptr inbounds i8, ptr %ptr, i32 4096 + %r = ptrtoint ptr %p2 to i32 + ret i32 %r +} + +define i32 @ptr_add_in_int_const_negative(i32 %x) { +; CHECK-LABEL: @ptr_add_in_int_const_negative( +; CHECK-NEXT: [[R:%.*]] = add i32 [[X:%.*]], -4096 +; CHECK-NEXT: ret i32 [[R]] +; + %ptr = inttoptr i32 %x to ptr + %p2 = getelementptr inbounds i8, ptr %ptr, i32 -4096 + %r = ptrtoint ptr %p2 to i32 + ret i32 %r +} + +declare void @use_ptr(ptr) + +define i32 @ptr_add_in_int_extra_use1(i32 %x) { +; CHECK-LABEL: @ptr_add_in_int_extra_use1( +; CHECK-NEXT: [[PTR:%.*]] = inttoptr i32 [[X:%.*]] to ptr +; CHECK-NEXT: call void @use_ptr(ptr [[PTR]]) +; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i32 4096 +; CHECK-NEXT: [[R:%.*]] = ptrtoint ptr [[P2]] to i32 +; CHECK-NEXT: ret i32 [[R]] +; + %ptr = inttoptr i32 %x to ptr + call void @use_ptr(ptr %ptr) + %p2 = getelementptr inbounds i8, ptr %ptr, i32 4096 + %r = ptrtoint ptr %p2 to i32 + ret i32 %r +} + +define i32 @ptr_add_in_int_extra_use2(i32 %x) { +; CHECK-LABEL: @ptr_add_in_int_extra_use2( +; CHECK-NEXT: [[PTR:%.*]] = inttoptr i32 [[X:%.*]] to ptr +; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i32 4096 +; CHECK-NEXT: call void @use_ptr(ptr nonnull [[P2]]) +; CHECK-NEXT: [[R:%.*]] = ptrtoint ptr [[P2]] to i32 +; CHECK-NEXT: ret i32 [[R]] +; + %ptr = inttoptr i32 %x to ptr + %p2 = getelementptr inbounds i8, ptr %ptr, i32 4096 + call void @use_ptr(ptr %p2) + %r = ptrtoint ptr %p2 to i32 + ret i32 %r +} -- GitLab From ebbbc73667a68dcfbe09392a1d34050592b234fd Mon Sep 17 00:00:00 2001 From: Chaitanya Date: Mon, 20 May 2024 10:24:40 +0530 Subject: [PATCH 049/793] [AMDGPU] Use removeFnAttrFromReachable in lower-module-lds pass. (#92686) --- .../AMDGPU/AMDGPULowerModuleLDSPass.cpp | 44 +------------------ 1 file changed, 1 insertion(+), 43 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp index 2c7163a77537..625ac0230f16 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp @@ -862,48 +862,6 @@ public: return N; } - /// Strip "amdgpu-no-lds-kernel-id" from any functions where we may have - /// introduced its use. If AMDGPUAttributor ran prior to the pass, we inferred - /// the lack of llvm.amdgcn.lds.kernel.id calls. - void removeNoLdsKernelIdFromReachable(CallGraph &CG, Function *KernelRoot) { - KernelRoot->removeFnAttr("amdgpu-no-lds-kernel-id"); - - SmallVector WorkList({CG[KernelRoot]->getFunction()}); - SmallPtrSet Visited; - bool SeenUnknownCall = false; - - while (!WorkList.empty()) { - Function *F = WorkList.pop_back_val(); - - for (auto &CallRecord : *CG[F]) { - if (!CallRecord.second) - continue; - - Function *Callee = CallRecord.second->getFunction(); - if (!Callee) { - if (!SeenUnknownCall) { - SeenUnknownCall = true; - - // If we see any indirect calls, assume nothing about potential - // targets. - // TODO: This could be refined to possible LDS global users. - for (auto &ExternalCallRecord : *CG.getExternalCallingNode()) { - Function *PotentialCallee = - ExternalCallRecord.second->getFunction(); - assert(PotentialCallee); - if (!isKernelLDS(PotentialCallee)) - PotentialCallee->removeFnAttr("amdgpu-no-lds-kernel-id"); - } - } - } else { - Callee->removeFnAttr("amdgpu-no-lds-kernel-id"); - if (Visited.insert(Callee).second) - WorkList.push_back(Callee); - } - } - } - } - DenseMap lowerDynamicLDSVariables( Module &M, LDSUsesInfoTy &LDSUsesInfo, DenseSet const &KernelsThatIndirectlyAllocateDynamicLDS, @@ -1059,7 +1017,7 @@ public: // // TODO: We could filter out subgraphs that do not access LDS globals. for (Function *F : KernelsThatAllocateTableLDS) - removeNoLdsKernelIdFromReachable(CG, F); + removeFnAttrFromReachable(CG, F, "amdgpu-no-lds-kernel-id"); } DenseMap KernelToCreatedDynamicLDS = -- GitLab From f6527774569790b5a5236f6e84f3f839ce6c2fff Mon Sep 17 00:00:00 2001 From: Austin Kerbow Date: Sun, 19 May 2024 22:01:10 -0700 Subject: [PATCH 050/793] [AMDGPU] Fix kernarg preloading crash with some types and alignments (#91625) Lowering of preloded arguments would fail with half/bfloat if they were dword aligned in the kernarg segment and not part of a vector. Added more tests with different alignments and types. --- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 20 +- llvm/test/CodeGen/AMDGPU/preload-kernargs.ll | 2231 ++++++++++-------- 2 files changed, 1231 insertions(+), 1020 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index 89e83babcfef..c7c4a8faa2fb 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -2976,12 +2976,20 @@ SDValue SITargetLowering::LowerFormalArguments( DL, Elts); } - SDValue CMemVT; - if (VT.isScalarInteger() && VT.bitsLT(NewArg.getSimpleValueType())) - CMemVT = DAG.getNode(ISD::TRUNCATE, DL, MemVT, NewArg); - else - CMemVT = DAG.getBitcast(MemVT, NewArg); - NewArg = convertArgType(DAG, VT, MemVT, DL, CMemVT, + // If the argument was preloaded to multiple consecutive 32-bit + // registers because of misalignment between addressable SGPR tuples + // and the argument size, we can still assume that because of kernarg + // segment alignment restrictions that NewArg's size is the same as + // MemVT and just do a bitcast. If MemVT is less than 32-bits we add a + // truncate since we cannot preload to less than a single SGPR and the + // MemVT may be smaller. + EVT MemVTInt = + EVT::getIntegerVT(*DAG.getContext(), MemVT.getSizeInBits()); + if (MemVT.bitsLT(NewArg.getSimpleValueType())) + NewArg = DAG.getNode(ISD::TRUNCATE, DL, MemVTInt, NewArg); + + NewArg = DAG.getBitcast(MemVT, NewArg); + NewArg = convertArgType(DAG, VT, MemVT, DL, NewArg, Ins[i].Flags.isSExt(), &Ins[i]); NewArg = DAG.getMergeValues({NewArg, Chain}, DL); } diff --git a/llvm/test/CodeGen/AMDGPU/preload-kernargs.ll b/llvm/test/CodeGen/AMDGPU/preload-kernargs.ll index f0e709b5a172..857bb897ead2 100644 --- a/llvm/test/CodeGen/AMDGPU/preload-kernargs.ll +++ b/llvm/test/CodeGen/AMDGPU/preload-kernargs.ll @@ -1,18 +1,14 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 ; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx940 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX940-NO-PRELOAD %s -; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx940 -amdgpu-kernarg-preload-count=1 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX940-PRELOAD-1 %s ; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx940 -amdgpu-kernarg-preload-count=2 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX940-PRELOAD-2 %s -; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx940 -amdgpu-kernarg-preload-count=4 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX940-PRELOAD-4 %s ; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx940 -amdgpu-kernarg-preload-count=8 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX940-PRELOAD-8 %s ; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx90a -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX90a-NO-PRELOAD %s -; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx90a -amdgpu-kernarg-preload-count=1 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX90a-PRELOAD-1 %s ; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx90a -amdgpu-kernarg-preload-count=2 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX90a-PRELOAD-2 %s -; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx90a -amdgpu-kernarg-preload-count=4 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX90a-PRELOAD-4 %s ; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx90a -amdgpu-kernarg-preload-count=8 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX90a-PRELOAD-8 %s -define amdgpu_kernel void @ptr1_i8(ptr addrspace(1) %out, i8 %arg0) { -; GFX940-NO-PRELOAD-LABEL: ptr1_i8: +define amdgpu_kernel void @ptr1_i8_kernel_preload_arg(ptr addrspace(1) %out, i8 %arg0) { +; GFX940-NO-PRELOAD-LABEL: ptr1_i8_kernel_preload_arg: ; GFX940-NO-PRELOAD: ; %bb.0: ; GFX940-NO-PRELOAD-NEXT: s_load_dword s4, s[0:1], 0x8 ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 @@ -23,19 +19,7 @@ define amdgpu_kernel void @ptr1_i8(ptr addrspace(1) %out, i8 %arg0) { ; GFX940-NO-PRELOAD-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: ptr1_i8: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dword s0, s[0:1], 0x8 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: s_and_b32 s0, s0, 0xff -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s0 -; GFX940-PRELOAD-1-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_endpgm -; -; GFX940-PRELOAD-2-LABEL: ptr1_i8: +; GFX940-PRELOAD-2-LABEL: ptr1_i8_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: @@ -45,17 +29,7 @@ define amdgpu_kernel void @ptr1_i8(ptr addrspace(1) %out, i8 %arg0) { ; GFX940-PRELOAD-2-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: ptr1_i8: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: s_and_b32 s0, s4, 0xff -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s0 -; GFX940-PRELOAD-4-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_endpgm -; -; GFX940-PRELOAD-8-LABEL: ptr1_i8: +; GFX940-PRELOAD-8-LABEL: ptr1_i8_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: @@ -65,7 +39,7 @@ define amdgpu_kernel void @ptr1_i8(ptr addrspace(1) %out, i8 %arg0) { ; GFX940-PRELOAD-8-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-PRELOAD-8-NEXT: s_endpgm ; -; GFX90a-NO-PRELOAD-LABEL: ptr1_i8: +; GFX90a-NO-PRELOAD-LABEL: ptr1_i8_kernel_preload_arg: ; GFX90a-NO-PRELOAD: ; %bb.0: ; GFX90a-NO-PRELOAD-NEXT: s_load_dword s2, s[4:5], 0x8 ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 @@ -76,19 +50,7 @@ define amdgpu_kernel void @ptr1_i8(ptr addrspace(1) %out, i8 %arg0) { ; GFX90a-NO-PRELOAD-NEXT: global_store_dword v0, v1, s[0:1] ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: ptr1_i8: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dword s0, s[4:5], 0x8 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: s_and_b32 s0, s0, 0xff -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s0 -; GFX90a-PRELOAD-1-NEXT: global_store_dword v0, v1, s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; -; GFX90a-PRELOAD-2-LABEL: ptr1_i8: +; GFX90a-PRELOAD-2-LABEL: ptr1_i8_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: @@ -98,17 +60,7 @@ define amdgpu_kernel void @ptr1_i8(ptr addrspace(1) %out, i8 %arg0) { ; GFX90a-PRELOAD-2-NEXT: global_store_dword v0, v1, s[6:7] ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: ptr1_i8: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: s_and_b32 s0, s8, 0xff -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s0 -; GFX90a-PRELOAD-4-NEXT: global_store_dword v0, v1, s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; -; GFX90a-PRELOAD-8-LABEL: ptr1_i8: +; GFX90a-PRELOAD-8-LABEL: ptr1_i8_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: @@ -122,8 +74,8 @@ define amdgpu_kernel void @ptr1_i8(ptr addrspace(1) %out, i8 %arg0) { ret void } -define amdgpu_kernel void @ptr1_i8_zext_arg(ptr addrspace(1) %out, i8 zeroext %arg0) { -; GFX940-NO-PRELOAD-LABEL: ptr1_i8_zext_arg: +define amdgpu_kernel void @ptr1_i8_zext_kernel_preload_arg(ptr addrspace(1) %out, i8 zeroext %arg0) { +; GFX940-NO-PRELOAD-LABEL: ptr1_i8_zext_kernel_preload_arg: ; GFX940-NO-PRELOAD: ; %bb.0: ; GFX940-NO-PRELOAD-NEXT: s_load_dword s4, s[0:1], 0x8 ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 @@ -134,19 +86,7 @@ define amdgpu_kernel void @ptr1_i8_zext_arg(ptr addrspace(1) %out, i8 zeroext %a ; GFX940-NO-PRELOAD-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: ptr1_i8_zext_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dword s0, s[0:1], 0x8 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: s_and_b32 s0, s0, 0xff -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s0 -; GFX940-PRELOAD-1-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_endpgm -; -; GFX940-PRELOAD-2-LABEL: ptr1_i8_zext_arg: +; GFX940-PRELOAD-2-LABEL: ptr1_i8_zext_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: @@ -157,18 +97,7 @@ define amdgpu_kernel void @ptr1_i8_zext_arg(ptr addrspace(1) %out, i8 zeroext %a ; GFX940-PRELOAD-2-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: ptr1_i8_zext_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: s_mov_b32 s0, 0xffff -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s4 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-4-NEXT: v_and_b32_sdwa v1, s0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:BYTE_0 -; GFX940-PRELOAD-4-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_endpgm -; -; GFX940-PRELOAD-8-LABEL: ptr1_i8_zext_arg: +; GFX940-PRELOAD-8-LABEL: ptr1_i8_zext_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: @@ -179,7 +108,7 @@ define amdgpu_kernel void @ptr1_i8_zext_arg(ptr addrspace(1) %out, i8 zeroext %a ; GFX940-PRELOAD-8-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-PRELOAD-8-NEXT: s_endpgm ; -; GFX90a-NO-PRELOAD-LABEL: ptr1_i8_zext_arg: +; GFX90a-NO-PRELOAD-LABEL: ptr1_i8_zext_kernel_preload_arg: ; GFX90a-NO-PRELOAD: ; %bb.0: ; GFX90a-NO-PRELOAD-NEXT: s_load_dword s2, s[4:5], 0x8 ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 @@ -190,19 +119,7 @@ define amdgpu_kernel void @ptr1_i8_zext_arg(ptr addrspace(1) %out, i8 zeroext %a ; GFX90a-NO-PRELOAD-NEXT: global_store_dword v0, v1, s[0:1] ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: ptr1_i8_zext_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dword s0, s[4:5], 0x8 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: s_and_b32 s0, s0, 0xff -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s0 -; GFX90a-PRELOAD-1-NEXT: global_store_dword v0, v1, s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; -; GFX90a-PRELOAD-2-LABEL: ptr1_i8_zext_arg: +; GFX90a-PRELOAD-2-LABEL: ptr1_i8_zext_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: @@ -213,18 +130,7 @@ define amdgpu_kernel void @ptr1_i8_zext_arg(ptr addrspace(1) %out, i8 zeroext %a ; GFX90a-PRELOAD-2-NEXT: global_store_dword v0, v1, s[6:7] ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: ptr1_i8_zext_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: s_mov_b32 s0, 0xffff -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s8 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-4-NEXT: v_and_b32_sdwa v1, s0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:BYTE_0 -; GFX90a-PRELOAD-4-NEXT: global_store_dword v0, v1, s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; -; GFX90a-PRELOAD-8-LABEL: ptr1_i8_zext_arg: +; GFX90a-PRELOAD-8-LABEL: ptr1_i8_zext_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: @@ -239,8 +145,8 @@ define amdgpu_kernel void @ptr1_i8_zext_arg(ptr addrspace(1) %out, i8 zeroext %a ret void } -define amdgpu_kernel void @ptr1_i16_preload_arg(ptr addrspace(1) %out, i16 %arg0) { -; GFX940-NO-PRELOAD-LABEL: ptr1_i16_preload_arg: +define amdgpu_kernel void @ptr1_i16_kernel_preload_arg(ptr addrspace(1) %out, i16 %arg0) { +; GFX940-NO-PRELOAD-LABEL: ptr1_i16_kernel_preload_arg: ; GFX940-NO-PRELOAD: ; %bb.0: ; GFX940-NO-PRELOAD-NEXT: s_load_dword s4, s[0:1], 0x8 ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 @@ -251,19 +157,7 @@ define amdgpu_kernel void @ptr1_i16_preload_arg(ptr addrspace(1) %out, i16 %arg0 ; GFX940-NO-PRELOAD-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: ptr1_i16_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dword s0, s[0:1], 0x8 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: s_and_b32 s0, s0, 0xffff -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s0 -; GFX940-PRELOAD-1-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_endpgm -; -; GFX940-PRELOAD-2-LABEL: ptr1_i16_preload_arg: +; GFX940-PRELOAD-2-LABEL: ptr1_i16_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: @@ -273,17 +167,7 @@ define amdgpu_kernel void @ptr1_i16_preload_arg(ptr addrspace(1) %out, i16 %arg0 ; GFX940-PRELOAD-2-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: ptr1_i16_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: s_and_b32 s0, s4, 0xffff -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s0 -; GFX940-PRELOAD-4-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_endpgm -; -; GFX940-PRELOAD-8-LABEL: ptr1_i16_preload_arg: +; GFX940-PRELOAD-8-LABEL: ptr1_i16_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: @@ -293,7 +177,7 @@ define amdgpu_kernel void @ptr1_i16_preload_arg(ptr addrspace(1) %out, i16 %arg0 ; GFX940-PRELOAD-8-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-PRELOAD-8-NEXT: s_endpgm ; -; GFX90a-NO-PRELOAD-LABEL: ptr1_i16_preload_arg: +; GFX90a-NO-PRELOAD-LABEL: ptr1_i16_kernel_preload_arg: ; GFX90a-NO-PRELOAD: ; %bb.0: ; GFX90a-NO-PRELOAD-NEXT: s_load_dword s2, s[4:5], 0x8 ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 @@ -304,19 +188,7 @@ define amdgpu_kernel void @ptr1_i16_preload_arg(ptr addrspace(1) %out, i16 %arg0 ; GFX90a-NO-PRELOAD-NEXT: global_store_dword v0, v1, s[0:1] ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: ptr1_i16_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dword s0, s[4:5], 0x8 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: s_and_b32 s0, s0, 0xffff -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s0 -; GFX90a-PRELOAD-1-NEXT: global_store_dword v0, v1, s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; -; GFX90a-PRELOAD-2-LABEL: ptr1_i16_preload_arg: +; GFX90a-PRELOAD-2-LABEL: ptr1_i16_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: @@ -326,17 +198,7 @@ define amdgpu_kernel void @ptr1_i16_preload_arg(ptr addrspace(1) %out, i16 %arg0 ; GFX90a-PRELOAD-2-NEXT: global_store_dword v0, v1, s[6:7] ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: ptr1_i16_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: s_and_b32 s0, s8, 0xffff -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s0 -; GFX90a-PRELOAD-4-NEXT: global_store_dword v0, v1, s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; -; GFX90a-PRELOAD-8-LABEL: ptr1_i16_preload_arg: +; GFX90a-PRELOAD-8-LABEL: ptr1_i16_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: @@ -350,8 +212,8 @@ define amdgpu_kernel void @ptr1_i16_preload_arg(ptr addrspace(1) %out, i16 %arg0 ret void } -define amdgpu_kernel void @ptr1_i32_preload_arg(ptr addrspace(1) %out, i32 %arg0) { -; GFX940-NO-PRELOAD-LABEL: ptr1_i32_preload_arg: +define amdgpu_kernel void @ptr1_i32_kernel_preload_arg(ptr addrspace(1) %out, i32 %arg0) { +; GFX940-NO-PRELOAD-LABEL: ptr1_i32_kernel_preload_arg: ; GFX940-NO-PRELOAD: ; %bb.0: ; GFX940-NO-PRELOAD-NEXT: s_load_dword s4, s[0:1], 0x8 ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 @@ -361,18 +223,7 @@ define amdgpu_kernel void @ptr1_i32_preload_arg(ptr addrspace(1) %out, i32 %arg0 ; GFX940-NO-PRELOAD-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: ptr1_i32_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dword s0, s[0:1], 0x8 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s0 -; GFX940-PRELOAD-1-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_endpgm -; -; GFX940-PRELOAD-2-LABEL: ptr1_i32_preload_arg: +; GFX940-PRELOAD-2-LABEL: ptr1_i32_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: @@ -381,16 +232,7 @@ define amdgpu_kernel void @ptr1_i32_preload_arg(ptr addrspace(1) %out, i32 %arg0 ; GFX940-PRELOAD-2-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: ptr1_i32_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s4 -; GFX940-PRELOAD-4-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_endpgm -; -; GFX940-PRELOAD-8-LABEL: ptr1_i32_preload_arg: +; GFX940-PRELOAD-8-LABEL: ptr1_i32_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: @@ -399,7 +241,7 @@ define amdgpu_kernel void @ptr1_i32_preload_arg(ptr addrspace(1) %out, i32 %arg0 ; GFX940-PRELOAD-8-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-PRELOAD-8-NEXT: s_endpgm ; -; GFX90a-NO-PRELOAD-LABEL: ptr1_i32_preload_arg: +; GFX90a-NO-PRELOAD-LABEL: ptr1_i32_kernel_preload_arg: ; GFX90a-NO-PRELOAD: ; %bb.0: ; GFX90a-NO-PRELOAD-NEXT: s_load_dword s2, s[4:5], 0x8 ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 @@ -409,18 +251,7 @@ define amdgpu_kernel void @ptr1_i32_preload_arg(ptr addrspace(1) %out, i32 %arg0 ; GFX90a-NO-PRELOAD-NEXT: global_store_dword v0, v1, s[0:1] ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: ptr1_i32_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dword s0, s[4:5], 0x8 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s0 -; GFX90a-PRELOAD-1-NEXT: global_store_dword v0, v1, s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; -; GFX90a-PRELOAD-2-LABEL: ptr1_i32_preload_arg: +; GFX90a-PRELOAD-2-LABEL: ptr1_i32_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: @@ -429,16 +260,7 @@ define amdgpu_kernel void @ptr1_i32_preload_arg(ptr addrspace(1) %out, i32 %arg0 ; GFX90a-PRELOAD-2-NEXT: global_store_dword v0, v1, s[6:7] ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: ptr1_i32_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s8 -; GFX90a-PRELOAD-4-NEXT: global_store_dword v0, v1, s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; -; GFX90a-PRELOAD-8-LABEL: ptr1_i32_preload_arg: +; GFX90a-PRELOAD-8-LABEL: ptr1_i32_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: @@ -451,8 +273,8 @@ define amdgpu_kernel void @ptr1_i32_preload_arg(ptr addrspace(1) %out, i32 %arg0 } -define amdgpu_kernel void @i32_ptr1_i32_preload_arg(i32 %arg0, ptr addrspace(1) %out, i32 %arg1) { -; GFX940-NO-PRELOAD-LABEL: i32_ptr1_i32_preload_arg: +define amdgpu_kernel void @i32_ptr1_i32_kernel_preload_arg(i32 %arg0, ptr addrspace(1) %out, i32 %arg1) { +; GFX940-NO-PRELOAD-LABEL: i32_ptr1_i32_kernel_preload_arg: ; GFX940-NO-PRELOAD: ; %bb.0: ; GFX940-NO-PRELOAD-NEXT: s_load_dword s4, s[0:1], 0x10 ; GFX940-NO-PRELOAD-NEXT: s_load_dword s5, s[0:1], 0x0 @@ -464,20 +286,7 @@ define amdgpu_kernel void @i32_ptr1_i32_preload_arg(i32 %arg0, ptr addrspace(1) ; GFX940-NO-PRELOAD-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: i32_ptr1_i32_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dword s3, s[0:1], 0x10 -; GFX940-PRELOAD-1-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x8 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: s_add_i32 s0, s2, s3 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s0 -; GFX940-PRELOAD-1-NEXT: global_store_dword v0, v1, s[4:5] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_endpgm -; -; GFX940-PRELOAD-2-LABEL: i32_ptr1_i32_preload_arg: +; GFX940-PRELOAD-2-LABEL: i32_ptr1_i32_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: @@ -489,17 +298,7 @@ define amdgpu_kernel void @i32_ptr1_i32_preload_arg(i32 %arg0, ptr addrspace(1) ; GFX940-PRELOAD-2-NEXT: global_store_dword v0, v1, s[4:5] sc0 sc1 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: i32_ptr1_i32_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: s_add_i32 s0, s2, s6 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s0 -; GFX940-PRELOAD-4-NEXT: global_store_dword v0, v1, s[4:5] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_endpgm -; -; GFX940-PRELOAD-8-LABEL: i32_ptr1_i32_preload_arg: +; GFX940-PRELOAD-8-LABEL: i32_ptr1_i32_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: @@ -509,7 +308,7 @@ define amdgpu_kernel void @i32_ptr1_i32_preload_arg(i32 %arg0, ptr addrspace(1) ; GFX940-PRELOAD-8-NEXT: global_store_dword v0, v1, s[4:5] sc0 sc1 ; GFX940-PRELOAD-8-NEXT: s_endpgm ; -; GFX90a-NO-PRELOAD-LABEL: i32_ptr1_i32_preload_arg: +; GFX90a-NO-PRELOAD-LABEL: i32_ptr1_i32_kernel_preload_arg: ; GFX90a-NO-PRELOAD: ; %bb.0: ; GFX90a-NO-PRELOAD-NEXT: s_load_dword s2, s[4:5], 0x10 ; GFX90a-NO-PRELOAD-NEXT: s_load_dword s3, s[4:5], 0x0 @@ -521,20 +320,7 @@ define amdgpu_kernel void @i32_ptr1_i32_preload_arg(i32 %arg0, ptr addrspace(1) ; GFX90a-NO-PRELOAD-NEXT: global_store_dword v0, v1, s[0:1] ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: i32_ptr1_i32_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dword s2, s[4:5], 0x10 -; GFX90a-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x8 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: s_add_i32 s2, s6, s2 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s2 -; GFX90a-PRELOAD-1-NEXT: global_store_dword v0, v1, s[0:1] -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; -; GFX90a-PRELOAD-2-LABEL: i32_ptr1_i32_preload_arg: +; GFX90a-PRELOAD-2-LABEL: i32_ptr1_i32_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: @@ -546,17 +332,7 @@ define amdgpu_kernel void @i32_ptr1_i32_preload_arg(i32 %arg0, ptr addrspace(1) ; GFX90a-PRELOAD-2-NEXT: global_store_dword v0, v1, s[8:9] ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: i32_ptr1_i32_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: s_add_i32 s0, s6, s10 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s0 -; GFX90a-PRELOAD-4-NEXT: global_store_dword v0, v1, s[8:9] -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; -; GFX90a-PRELOAD-8-LABEL: i32_ptr1_i32_preload_arg: +; GFX90a-PRELOAD-8-LABEL: i32_ptr1_i32_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: @@ -570,8 +346,8 @@ define amdgpu_kernel void @i32_ptr1_i32_preload_arg(i32 %arg0, ptr addrspace(1) ret void } -define amdgpu_kernel void @ptr1_i16_i16_preload_arg(ptr addrspace(1) %out, i16 %arg0, i16 %arg1) { -; GFX940-NO-PRELOAD-LABEL: ptr1_i16_i16_preload_arg: +define amdgpu_kernel void @ptr1_i16_i16_kernel_preload_arg(ptr addrspace(1) %out, i16 %arg0, i16 %arg1) { +; GFX940-NO-PRELOAD-LABEL: ptr1_i16_i16_kernel_preload_arg: ; GFX940-NO-PRELOAD: ; %bb.0: ; GFX940-NO-PRELOAD-NEXT: s_load_dword s4, s[0:1], 0x8 ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 @@ -584,21 +360,7 @@ define amdgpu_kernel void @ptr1_i16_i16_preload_arg(ptr addrspace(1) %out, i16 % ; GFX940-NO-PRELOAD-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: ptr1_i16_i16_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dword s0, s[0:1], 0x8 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: s_lshr_b32 s1, s0, 16 -; GFX940-PRELOAD-1-NEXT: s_and_b32 s0, s0, 0xffff -; GFX940-PRELOAD-1-NEXT: s_add_i32 s0, s0, s1 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s0 -; GFX940-PRELOAD-1-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_endpgm -; -; GFX940-PRELOAD-2-LABEL: ptr1_i16_i16_preload_arg: +; GFX940-PRELOAD-2-LABEL: ptr1_i16_i16_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: @@ -612,19 +374,7 @@ define amdgpu_kernel void @ptr1_i16_i16_preload_arg(ptr addrspace(1) %out, i16 % ; GFX940-PRELOAD-2-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: ptr1_i16_i16_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: s_lshr_b32 s0, s4, 16 -; GFX940-PRELOAD-4-NEXT: s_and_b32 s1, s4, 0xffff -; GFX940-PRELOAD-4-NEXT: s_add_i32 s0, s1, s0 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s0 -; GFX940-PRELOAD-4-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_endpgm -; -; GFX940-PRELOAD-8-LABEL: ptr1_i16_i16_preload_arg: +; GFX940-PRELOAD-8-LABEL: ptr1_i16_i16_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: @@ -636,7 +386,7 @@ define amdgpu_kernel void @ptr1_i16_i16_preload_arg(ptr addrspace(1) %out, i16 % ; GFX940-PRELOAD-8-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-PRELOAD-8-NEXT: s_endpgm ; -; GFX90a-NO-PRELOAD-LABEL: ptr1_i16_i16_preload_arg: +; GFX90a-NO-PRELOAD-LABEL: ptr1_i16_i16_kernel_preload_arg: ; GFX90a-NO-PRELOAD: ; %bb.0: ; GFX90a-NO-PRELOAD-NEXT: s_load_dword s2, s[4:5], 0x8 ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 @@ -649,21 +399,7 @@ define amdgpu_kernel void @ptr1_i16_i16_preload_arg(ptr addrspace(1) %out, i16 % ; GFX90a-NO-PRELOAD-NEXT: global_store_dword v0, v1, s[0:1] ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: ptr1_i16_i16_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dword s0, s[4:5], 0x8 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: s_lshr_b32 s1, s0, 16 -; GFX90a-PRELOAD-1-NEXT: s_and_b32 s0, s0, 0xffff -; GFX90a-PRELOAD-1-NEXT: s_add_i32 s0, s0, s1 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s0 -; GFX90a-PRELOAD-1-NEXT: global_store_dword v0, v1, s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; -; GFX90a-PRELOAD-2-LABEL: ptr1_i16_i16_preload_arg: +; GFX90a-PRELOAD-2-LABEL: ptr1_i16_i16_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: @@ -677,19 +413,7 @@ define amdgpu_kernel void @ptr1_i16_i16_preload_arg(ptr addrspace(1) %out, i16 % ; GFX90a-PRELOAD-2-NEXT: global_store_dword v0, v1, s[6:7] ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: ptr1_i16_i16_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: s_lshr_b32 s0, s8, 16 -; GFX90a-PRELOAD-4-NEXT: s_and_b32 s1, s8, 0xffff -; GFX90a-PRELOAD-4-NEXT: s_add_i32 s0, s1, s0 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s0 -; GFX90a-PRELOAD-4-NEXT: global_store_dword v0, v1, s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; -; GFX90a-PRELOAD-8-LABEL: ptr1_i16_i16_preload_arg: +; GFX90a-PRELOAD-8-LABEL: ptr1_i16_i16_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: @@ -707,8 +431,8 @@ define amdgpu_kernel void @ptr1_i16_i16_preload_arg(ptr addrspace(1) %out, i16 % ret void } -define amdgpu_kernel void @ptr1_v2i8_preload_arg(ptr addrspace(1) %out, <2 x i8> %in) { -; GFX940-NO-PRELOAD-LABEL: ptr1_v2i8_preload_arg: +define amdgpu_kernel void @ptr1_v2i8_kernel_preload_arg(ptr addrspace(1) %out, <2 x i8> %in) { +; GFX940-NO-PRELOAD-LABEL: ptr1_v2i8_kernel_preload_arg: ; GFX940-NO-PRELOAD: ; %bb.0: ; GFX940-NO-PRELOAD-NEXT: s_load_dword s4, s[0:1], 0x8 ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 @@ -718,18 +442,7 @@ define amdgpu_kernel void @ptr1_v2i8_preload_arg(ptr addrspace(1) %out, <2 x i8> ; GFX940-NO-PRELOAD-NEXT: global_store_short v0, v1, s[2:3] sc0 sc1 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: ptr1_v2i8_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dword s0, s[0:1], 0x8 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s0 -; GFX940-PRELOAD-1-NEXT: global_store_short v0, v1, s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_endpgm -; -; GFX940-PRELOAD-2-LABEL: ptr1_v2i8_preload_arg: +; GFX940-PRELOAD-2-LABEL: ptr1_v2i8_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: @@ -740,18 +453,7 @@ define amdgpu_kernel void @ptr1_v2i8_preload_arg(ptr addrspace(1) %out, <2 x i8> ; GFX940-PRELOAD-2-NEXT: global_store_short v1, v0, s[2:3] sc0 sc1 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: ptr1_v2i8_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: s_lshr_b32 s0, s4, 8 -; GFX940-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v0, 8, s0 -; GFX940-PRELOAD-4-NEXT: v_or_b32_sdwa v0, s4, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, 0 -; GFX940-PRELOAD-4-NEXT: global_store_short v1, v0, s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_endpgm -; -; GFX940-PRELOAD-8-LABEL: ptr1_v2i8_preload_arg: +; GFX940-PRELOAD-8-LABEL: ptr1_v2i8_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: @@ -762,7 +464,7 @@ define amdgpu_kernel void @ptr1_v2i8_preload_arg(ptr addrspace(1) %out, <2 x i8> ; GFX940-PRELOAD-8-NEXT: global_store_short v1, v0, s[2:3] sc0 sc1 ; GFX940-PRELOAD-8-NEXT: s_endpgm ; -; GFX90a-NO-PRELOAD-LABEL: ptr1_v2i8_preload_arg: +; GFX90a-NO-PRELOAD-LABEL: ptr1_v2i8_kernel_preload_arg: ; GFX90a-NO-PRELOAD: ; %bb.0: ; GFX90a-NO-PRELOAD-NEXT: s_load_dword s2, s[4:5], 0x8 ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 @@ -772,18 +474,7 @@ define amdgpu_kernel void @ptr1_v2i8_preload_arg(ptr addrspace(1) %out, <2 x i8> ; GFX90a-NO-PRELOAD-NEXT: global_store_short v0, v1, s[0:1] ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: ptr1_v2i8_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dword s0, s[4:5], 0x8 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s0 -; GFX90a-PRELOAD-1-NEXT: global_store_short v0, v1, s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; -; GFX90a-PRELOAD-2-LABEL: ptr1_v2i8_preload_arg: +; GFX90a-PRELOAD-2-LABEL: ptr1_v2i8_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: @@ -794,18 +485,7 @@ define amdgpu_kernel void @ptr1_v2i8_preload_arg(ptr addrspace(1) %out, <2 x i8> ; GFX90a-PRELOAD-2-NEXT: global_store_short v1, v0, s[6:7] ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: ptr1_v2i8_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: s_lshr_b32 s0, s8, 8 -; GFX90a-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v0, 8, s0 -; GFX90a-PRELOAD-4-NEXT: v_or_b32_sdwa v0, s8, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, 0 -; GFX90a-PRELOAD-4-NEXT: global_store_short v1, v0, s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; -; GFX90a-PRELOAD-8-LABEL: ptr1_v2i8_preload_arg: +; GFX90a-PRELOAD-8-LABEL: ptr1_v2i8_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: @@ -820,8 +500,8 @@ define amdgpu_kernel void @ptr1_v2i8_preload_arg(ptr addrspace(1) %out, <2 x i8> } -define amdgpu_kernel void @byref_preload_arg(ptr addrspace(1) %out, ptr addrspace(4) byref(i32) align(256) %in.byref, i32 %after.offset) { -; GFX940-NO-PRELOAD-LABEL: byref_preload_arg: +define amdgpu_kernel void @byref_kernel_preload_arg(ptr addrspace(1) %out, ptr addrspace(4) byref(i32) align(256) %in.byref, i32 %after.offset) { +; GFX940-NO-PRELOAD-LABEL: byref_kernel_preload_arg: ; GFX940-NO-PRELOAD: ; %bb.0: ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x100 ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 @@ -835,22 +515,7 @@ define amdgpu_kernel void @byref_preload_arg(ptr addrspace(1) %out, ptr addrspac ; GFX940-NO-PRELOAD-NEXT: s_waitcnt vmcnt(0) ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: byref_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x100 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s0 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s1 -; GFX940-PRELOAD-1-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_waitcnt vmcnt(0) -; GFX940-PRELOAD-1-NEXT: global_store_dword v0, v2, s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_waitcnt vmcnt(0) -; GFX940-PRELOAD-1-NEXT: s_endpgm -; -; GFX940-PRELOAD-2-LABEL: byref_preload_arg: +; GFX940-PRELOAD-2-LABEL: byref_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: @@ -865,22 +530,7 @@ define amdgpu_kernel void @byref_preload_arg(ptr addrspace(1) %out, ptr addrspac ; GFX940-PRELOAD-2-NEXT: s_waitcnt vmcnt(0) ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: byref_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x100 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-4-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s0 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v2, s1 -; GFX940-PRELOAD-4-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_waitcnt vmcnt(0) -; GFX940-PRELOAD-4-NEXT: global_store_dword v0, v2, s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_waitcnt vmcnt(0) -; GFX940-PRELOAD-4-NEXT: s_endpgm -; -; GFX940-PRELOAD-8-LABEL: byref_preload_arg: +; GFX940-PRELOAD-8-LABEL: byref_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: @@ -895,7 +545,7 @@ define amdgpu_kernel void @byref_preload_arg(ptr addrspace(1) %out, ptr addrspac ; GFX940-PRELOAD-8-NEXT: s_waitcnt vmcnt(0) ; GFX940-PRELOAD-8-NEXT: s_endpgm ; -; GFX90a-NO-PRELOAD-LABEL: byref_preload_arg: +; GFX90a-NO-PRELOAD-LABEL: byref_kernel_preload_arg: ; GFX90a-NO-PRELOAD: ; %bb.0: ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x100 ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[4:5], 0x0 @@ -909,22 +559,7 @@ define amdgpu_kernel void @byref_preload_arg(ptr addrspace(1) %out, ptr addrspac ; GFX90a-NO-PRELOAD-NEXT: s_waitcnt vmcnt(0) ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: byref_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x100 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s0 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s1 -; GFX90a-PRELOAD-1-NEXT: global_store_dword v0, v1, s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_waitcnt vmcnt(0) -; GFX90a-PRELOAD-1-NEXT: global_store_dword v0, v2, s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_waitcnt vmcnt(0) -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; -; GFX90a-PRELOAD-2-LABEL: byref_preload_arg: +; GFX90a-PRELOAD-2-LABEL: byref_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: @@ -939,22 +574,7 @@ define amdgpu_kernel void @byref_preload_arg(ptr addrspace(1) %out, ptr addrspac ; GFX90a-PRELOAD-2-NEXT: s_waitcnt vmcnt(0) ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: byref_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x100 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-4-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s0 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v2, s1 -; GFX90a-PRELOAD-4-NEXT: global_store_dword v0, v1, s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_waitcnt vmcnt(0) -; GFX90a-PRELOAD-4-NEXT: global_store_dword v0, v2, s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_waitcnt vmcnt(0) -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; -; GFX90a-PRELOAD-8-LABEL: byref_preload_arg: +; GFX90a-PRELOAD-8-LABEL: byref_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: @@ -975,8 +595,8 @@ define amdgpu_kernel void @byref_preload_arg(ptr addrspace(1) %out, ptr addrspac } -define amdgpu_kernel void @v8i32_arg(ptr addrspace(1) nocapture %out, <8 x i32> %in) nounwind { -; GFX940-NO-PRELOAD-LABEL: v8i32_arg: +define amdgpu_kernel void @v8i32_kernel_preload_arg(ptr addrspace(1) nocapture %out, <8 x i32> %in) nounwind { +; GFX940-NO-PRELOAD-LABEL: v8i32_kernel_preload_arg: ; GFX940-NO-PRELOAD: ; %bb.0: ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx8 s[4:11], s[0:1], 0x20 ; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v4, 0 @@ -995,27 +615,7 @@ define amdgpu_kernel void @v8i32_arg(ptr addrspace(1) nocapture %out, <8 x i32> ; GFX940-NO-PRELOAD-NEXT: global_store_dwordx4 v4, v[0:3], s[0:1] sc0 sc1 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: v8i32_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dwordx8 s[4:11], s[0:1], 0x20 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v4, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, s8 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s9 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s10 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v3, s11 -; GFX940-PRELOAD-1-NEXT: global_store_dwordx4 v4, v[0:3], s[2:3] offset:16 sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_nop 1 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, s4 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s5 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s6 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v3, s7 -; GFX940-PRELOAD-1-NEXT: global_store_dwordx4 v4, v[0:3], s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_endpgm -; -; GFX940-PRELOAD-2-LABEL: v8i32_arg: +; GFX940-PRELOAD-2-LABEL: v8i32_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: @@ -1035,27 +635,7 @@ define amdgpu_kernel void @v8i32_arg(ptr addrspace(1) nocapture %out, <8 x i32> ; GFX940-PRELOAD-2-NEXT: global_store_dwordx4 v4, v[0:3], s[2:3] sc0 sc1 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: v8i32_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: s_load_dwordx8 s[4:11], s[0:1], 0x20 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v4, 0 -; GFX940-PRELOAD-4-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, s8 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s9 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v2, s10 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v3, s11 -; GFX940-PRELOAD-4-NEXT: global_store_dwordx4 v4, v[0:3], s[2:3] offset:16 sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_nop 1 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, s4 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s5 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v2, s6 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v3, s7 -; GFX940-PRELOAD-4-NEXT: global_store_dwordx4 v4, v[0:3], s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_endpgm -; -; GFX940-PRELOAD-8-LABEL: v8i32_arg: +; GFX940-PRELOAD-8-LABEL: v8i32_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: @@ -1075,7 +655,7 @@ define amdgpu_kernel void @v8i32_arg(ptr addrspace(1) nocapture %out, <8 x i32> ; GFX940-PRELOAD-8-NEXT: global_store_dwordx4 v4, v[0:3], s[2:3] sc0 sc1 ; GFX940-PRELOAD-8-NEXT: s_endpgm ; -; GFX90a-NO-PRELOAD-LABEL: v8i32_arg: +; GFX90a-NO-PRELOAD-LABEL: v8i32_kernel_preload_arg: ; GFX90a-NO-PRELOAD: ; %bb.0: ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx8 s[8:15], s[4:5], 0x20 ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 @@ -1094,27 +674,7 @@ define amdgpu_kernel void @v8i32_arg(ptr addrspace(1) nocapture %out, <8 x i32> ; GFX90a-NO-PRELOAD-NEXT: global_store_dwordx4 v4, v[0:3], s[0:1] ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: v8i32_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dwordx8 s[8:15], s[4:5], 0x20 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v4, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, s12 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s13 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s14 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v3, s15 -; GFX90a-PRELOAD-1-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] offset:16 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, s8 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s9 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s10 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v3, s11 -; GFX90a-PRELOAD-1-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; -; GFX90a-PRELOAD-2-LABEL: v8i32_arg: +; GFX90a-PRELOAD-2-LABEL: v8i32_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: @@ -1134,27 +694,7 @@ define amdgpu_kernel void @v8i32_arg(ptr addrspace(1) nocapture %out, <8 x i32> ; GFX90a-PRELOAD-2-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: v8i32_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: s_load_dwordx8 s[8:15], s[4:5], 0x20 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v4, 0 -; GFX90a-PRELOAD-4-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, s12 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s13 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v2, s14 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v3, s15 -; GFX90a-PRELOAD-4-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] offset:16 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, s8 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s9 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v2, s10 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v3, s11 -; GFX90a-PRELOAD-4-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; -; GFX90a-PRELOAD-8-LABEL: v8i32_arg: +; GFX90a-PRELOAD-8-LABEL: v8i32_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: @@ -1177,8 +717,8 @@ define amdgpu_kernel void @v8i32_arg(ptr addrspace(1) nocapture %out, <8 x i32> ret void } -define amdgpu_kernel void @v3i16_preload_arg(ptr addrspace(1) nocapture %out, <3 x i16> %in) nounwind { -; GFX940-NO-PRELOAD-LABEL: v3i16_preload_arg: +define amdgpu_kernel void @v3i16_kernel_preload_arg(ptr addrspace(1) nocapture %out, <3 x i16> %in) nounwind { +; GFX940-NO-PRELOAD-LABEL: v3i16_kernel_preload_arg: ; GFX940-NO-PRELOAD: ; %bb.0: ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 ; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 @@ -1189,20 +729,7 @@ define amdgpu_kernel void @v3i16_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-NO-PRELOAD-NEXT: global_store_dword v0, v2, s[0:1] sc0 sc1 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: v3i16_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x8 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s1 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s0 -; GFX940-PRELOAD-1-NEXT: global_store_short v0, v1, s[2:3] offset:4 sc0 sc1 -; GFX940-PRELOAD-1-NEXT: global_store_dword v0, v2, s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_endpgm -; -; GFX940-PRELOAD-2-LABEL: v3i16_preload_arg: +; GFX940-PRELOAD-2-LABEL: v3i16_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: @@ -1213,18 +740,7 @@ define amdgpu_kernel void @v3i16_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-PRELOAD-2-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: v3i16_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s5 -; GFX940-PRELOAD-4-NEXT: global_store_short v0, v1, s[2:3] offset:4 sc0 sc1 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s4 -; GFX940-PRELOAD-4-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_endpgm -; -; GFX940-PRELOAD-8-LABEL: v3i16_preload_arg: +; GFX940-PRELOAD-8-LABEL: v3i16_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: @@ -1235,7 +751,7 @@ define amdgpu_kernel void @v3i16_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-PRELOAD-8-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 ; GFX940-PRELOAD-8-NEXT: s_endpgm ; -; GFX90a-NO-PRELOAD-LABEL: v3i16_preload_arg: +; GFX90a-NO-PRELOAD-LABEL: v3i16_kernel_preload_arg: ; GFX90a-NO-PRELOAD: ; %bb.0: ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 ; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 @@ -1246,20 +762,7 @@ define amdgpu_kernel void @v3i16_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-NO-PRELOAD-NEXT: global_store_dword v0, v2, s[0:1] ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: v3i16_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x8 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s1 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s0 -; GFX90a-PRELOAD-1-NEXT: global_store_short v0, v1, s[6:7] offset:4 -; GFX90a-PRELOAD-1-NEXT: global_store_dword v0, v2, s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; -; GFX90a-PRELOAD-2-LABEL: v3i16_preload_arg: +; GFX90a-PRELOAD-2-LABEL: v3i16_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: @@ -1270,18 +773,7 @@ define amdgpu_kernel void @v3i16_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-PRELOAD-2-NEXT: global_store_dword v0, v1, s[6:7] ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: v3i16_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s9 -; GFX90a-PRELOAD-4-NEXT: global_store_short v0, v1, s[6:7] offset:4 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s8 -; GFX90a-PRELOAD-4-NEXT: global_store_dword v0, v1, s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; -; GFX90a-PRELOAD-8-LABEL: v3i16_preload_arg: +; GFX90a-PRELOAD-8-LABEL: v3i16_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: @@ -1295,8 +787,8 @@ define amdgpu_kernel void @v3i16_preload_arg(ptr addrspace(1) nocapture %out, <3 ret void } -define amdgpu_kernel void @v3i32_preload_arg(ptr addrspace(1) nocapture %out, <3 x i32> %in) nounwind { -; GFX940-NO-PRELOAD-LABEL: v3i32_preload_arg: +define amdgpu_kernel void @v3i32_kernel_preload_arg(ptr addrspace(1) nocapture %out, <3 x i32> %in) nounwind { +; GFX940-NO-PRELOAD-LABEL: v3i32_kernel_preload_arg: ; GFX940-NO-PRELOAD: ; %bb.0: ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x10 ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 @@ -1308,20 +800,7 @@ define amdgpu_kernel void @v3i32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-NO-PRELOAD-NEXT: global_store_dwordx3 v3, v[0:2], s[2:3] sc0 sc1 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: v3i32_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x10 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v3, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, s4 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s5 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s6 -; GFX940-PRELOAD-1-NEXT: global_store_dwordx3 v3, v[0:2], s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_endpgm -; -; GFX940-PRELOAD-2-LABEL: v3i32_preload_arg: +; GFX940-PRELOAD-2-LABEL: v3i32_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: @@ -1332,18 +811,7 @@ define amdgpu_kernel void @v3i32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-PRELOAD-2-NEXT: global_store_dwordx3 v3, v[0:2], s[2:3] sc0 sc1 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: v3i32_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, s6 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s7 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v2, s8 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v3, 0 -; GFX940-PRELOAD-4-NEXT: global_store_dwordx3 v3, v[0:2], s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_endpgm -; -; GFX940-PRELOAD-8-LABEL: v3i32_preload_arg: +; GFX940-PRELOAD-8-LABEL: v3i32_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: @@ -1354,7 +822,7 @@ define amdgpu_kernel void @v3i32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-PRELOAD-8-NEXT: global_store_dwordx3 v3, v[0:2], s[2:3] sc0 sc1 ; GFX940-PRELOAD-8-NEXT: s_endpgm ; -; GFX90a-NO-PRELOAD-LABEL: v3i32_preload_arg: +; GFX90a-NO-PRELOAD-LABEL: v3i32_kernel_preload_arg: ; GFX90a-NO-PRELOAD: ; %bb.0: ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x10 ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[6:7], s[4:5], 0x0 @@ -1366,20 +834,7 @@ define amdgpu_kernel void @v3i32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-NO-PRELOAD-NEXT: global_store_dwordx3 v3, v[0:2], s[6:7] ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: v3i32_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x10 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v3, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, s0 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s1 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s2 -; GFX90a-PRELOAD-1-NEXT: global_store_dwordx3 v3, v[0:2], s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; -; GFX90a-PRELOAD-2-LABEL: v3i32_preload_arg: +; GFX90a-PRELOAD-2-LABEL: v3i32_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: @@ -1390,18 +845,7 @@ define amdgpu_kernel void @v3i32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-PRELOAD-2-NEXT: global_store_dwordx3 v3, v[0:2], s[6:7] ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: v3i32_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, s10 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s11 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v2, s12 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v3, 0 -; GFX90a-PRELOAD-4-NEXT: global_store_dwordx3 v3, v[0:2], s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; -; GFX90a-PRELOAD-8-LABEL: v3i32_preload_arg: +; GFX90a-PRELOAD-8-LABEL: v3i32_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: @@ -1415,8 +859,8 @@ define amdgpu_kernel void @v3i32_preload_arg(ptr addrspace(1) nocapture %out, <3 ret void } -define amdgpu_kernel void @v3f32_preload_arg(ptr addrspace(1) nocapture %out, <3 x float> %in) nounwind { -; GFX940-NO-PRELOAD-LABEL: v3f32_preload_arg: +define amdgpu_kernel void @v3f32_kernel_preload_arg(ptr addrspace(1) nocapture %out, <3 x float> %in) nounwind { +; GFX940-NO-PRELOAD-LABEL: v3f32_kernel_preload_arg: ; GFX940-NO-PRELOAD: ; %bb.0: ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x10 ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 @@ -1428,20 +872,7 @@ define amdgpu_kernel void @v3f32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-NO-PRELOAD-NEXT: global_store_dwordx3 v3, v[0:2], s[2:3] sc0 sc1 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: v3f32_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x10 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v3, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, s4 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s5 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s6 -; GFX940-PRELOAD-1-NEXT: global_store_dwordx3 v3, v[0:2], s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_endpgm -; -; GFX940-PRELOAD-2-LABEL: v3f32_preload_arg: +; GFX940-PRELOAD-2-LABEL: v3f32_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: @@ -1452,18 +883,7 @@ define amdgpu_kernel void @v3f32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-PRELOAD-2-NEXT: global_store_dwordx3 v3, v[0:2], s[2:3] sc0 sc1 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: v3f32_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v3, 0 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, s6 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s7 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v2, s8 -; GFX940-PRELOAD-4-NEXT: global_store_dwordx3 v3, v[0:2], s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_endpgm -; -; GFX940-PRELOAD-8-LABEL: v3f32_preload_arg: +; GFX940-PRELOAD-8-LABEL: v3f32_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: @@ -1474,7 +894,7 @@ define amdgpu_kernel void @v3f32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-PRELOAD-8-NEXT: global_store_dwordx3 v3, v[0:2], s[2:3] sc0 sc1 ; GFX940-PRELOAD-8-NEXT: s_endpgm ; -; GFX90a-NO-PRELOAD-LABEL: v3f32_preload_arg: +; GFX90a-NO-PRELOAD-LABEL: v3f32_kernel_preload_arg: ; GFX90a-NO-PRELOAD: ; %bb.0: ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x10 ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[6:7], s[4:5], 0x0 @@ -1486,20 +906,7 @@ define amdgpu_kernel void @v3f32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-NO-PRELOAD-NEXT: global_store_dwordx3 v3, v[0:2], s[6:7] ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: v3f32_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x10 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v3, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, s0 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s1 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s2 -; GFX90a-PRELOAD-1-NEXT: global_store_dwordx3 v3, v[0:2], s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; -; GFX90a-PRELOAD-2-LABEL: v3f32_preload_arg: +; GFX90a-PRELOAD-2-LABEL: v3f32_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: @@ -1510,18 +917,7 @@ define amdgpu_kernel void @v3f32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-PRELOAD-2-NEXT: global_store_dwordx3 v3, v[0:2], s[6:7] ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: v3f32_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v3, 0 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, s10 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s11 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v2, s12 -; GFX90a-PRELOAD-4-NEXT: global_store_dwordx3 v3, v[0:2], s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; -; GFX90a-PRELOAD-8-LABEL: v3f32_preload_arg: +; GFX90a-PRELOAD-8-LABEL: v3f32_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: @@ -1535,8 +931,8 @@ define amdgpu_kernel void @v3f32_preload_arg(ptr addrspace(1) nocapture %out, <3 ret void } -define amdgpu_kernel void @v5i8_preload_arg(ptr addrspace(1) nocapture %out, <5 x i8> %in) nounwind { -; GFX940-NO-PRELOAD-LABEL: v5i8_preload_arg: +define amdgpu_kernel void @v5i8_kernel_preload_arg(ptr addrspace(1) nocapture %out, <5 x i8> %in) nounwind { +; GFX940-NO-PRELOAD-LABEL: v5i8_kernel_preload_arg: ; GFX940-NO-PRELOAD: ; %bb.0: ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 ; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 @@ -1547,20 +943,7 @@ define amdgpu_kernel void @v5i8_preload_arg(ptr addrspace(1) nocapture %out, <5 ; GFX940-NO-PRELOAD-NEXT: global_store_dword v0, v2, s[0:1] sc0 sc1 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: v5i8_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x8 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s1 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s0 -; GFX940-PRELOAD-1-NEXT: global_store_byte v0, v1, s[2:3] offset:4 sc0 sc1 -; GFX940-PRELOAD-1-NEXT: global_store_dword v0, v2, s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_endpgm -; -; GFX940-PRELOAD-2-LABEL: v5i8_preload_arg: +; GFX940-PRELOAD-2-LABEL: v5i8_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: @@ -1578,25 +961,7 @@ define amdgpu_kernel void @v5i8_preload_arg(ptr addrspace(1) nocapture %out, <5 ; GFX940-PRELOAD-2-NEXT: global_store_dword v1, v0, s[2:3] sc0 sc1 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: v5i8_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: s_lshr_b32 s0, s4, 8 -; GFX940-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v0, 8, s0 -; GFX940-PRELOAD-4-NEXT: s_lshr_b32 s0, s4, 24 -; GFX940-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v1, 8, s0 -; GFX940-PRELOAD-4-NEXT: s_lshr_b32 s0, s4, 16 -; GFX940-PRELOAD-4-NEXT: v_or_b32_sdwa v0, s4, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX940-PRELOAD-4-NEXT: v_or_b32_sdwa v1, s0, v1 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v2, s5 -; GFX940-PRELOAD-4-NEXT: v_or_b32_sdwa v0, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, 0 -; GFX940-PRELOAD-4-NEXT: global_store_byte v1, v2, s[2:3] offset:4 sc0 sc1 -; GFX940-PRELOAD-4-NEXT: global_store_dword v1, v0, s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_endpgm -; -; GFX940-PRELOAD-8-LABEL: v5i8_preload_arg: +; GFX940-PRELOAD-8-LABEL: v5i8_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: @@ -1614,7 +979,7 @@ define amdgpu_kernel void @v5i8_preload_arg(ptr addrspace(1) nocapture %out, <5 ; GFX940-PRELOAD-8-NEXT: global_store_dword v1, v0, s[2:3] sc0 sc1 ; GFX940-PRELOAD-8-NEXT: s_endpgm ; -; GFX90a-NO-PRELOAD-LABEL: v5i8_preload_arg: +; GFX90a-NO-PRELOAD-LABEL: v5i8_kernel_preload_arg: ; GFX90a-NO-PRELOAD: ; %bb.0: ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 ; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 @@ -1625,20 +990,7 @@ define amdgpu_kernel void @v5i8_preload_arg(ptr addrspace(1) nocapture %out, <5 ; GFX90a-NO-PRELOAD-NEXT: global_store_dword v0, v2, s[0:1] ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: v5i8_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x8 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s1 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s0 -; GFX90a-PRELOAD-1-NEXT: global_store_byte v0, v1, s[6:7] offset:4 -; GFX90a-PRELOAD-1-NEXT: global_store_dword v0, v2, s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; -; GFX90a-PRELOAD-2-LABEL: v5i8_preload_arg: +; GFX90a-PRELOAD-2-LABEL: v5i8_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: @@ -1656,25 +1008,7 @@ define amdgpu_kernel void @v5i8_preload_arg(ptr addrspace(1) nocapture %out, <5 ; GFX90a-PRELOAD-2-NEXT: global_store_dword v1, v0, s[6:7] ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: v5i8_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: s_lshr_b32 s0, s8, 8 -; GFX90a-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v0, 8, s0 -; GFX90a-PRELOAD-4-NEXT: s_lshr_b32 s0, s8, 24 -; GFX90a-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v1, 8, s0 -; GFX90a-PRELOAD-4-NEXT: s_lshr_b32 s0, s8, 16 -; GFX90a-PRELOAD-4-NEXT: v_or_b32_sdwa v0, s8, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX90a-PRELOAD-4-NEXT: v_or_b32_sdwa v1, s0, v1 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX90a-PRELOAD-4-NEXT: v_or_b32_sdwa v0, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, 0 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v2, s9 -; GFX90a-PRELOAD-4-NEXT: global_store_byte v1, v2, s[6:7] offset:4 -; GFX90a-PRELOAD-4-NEXT: global_store_dword v1, v0, s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; -; GFX90a-PRELOAD-8-LABEL: v5i8_preload_arg: +; GFX90a-PRELOAD-8-LABEL: v5i8_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: @@ -1695,8 +1029,8 @@ define amdgpu_kernel void @v5i8_preload_arg(ptr addrspace(1) nocapture %out, <5 ret void } -define amdgpu_kernel void @v5f64_arg(ptr addrspace(1) nocapture %out, <5 x double> %in) nounwind { -; GFX940-NO-PRELOAD-LABEL: v5f64_arg: +define amdgpu_kernel void @v5f64_kernel_preload_arg(ptr addrspace(1) nocapture %out, <5 x double> %in) nounwind { +; GFX940-NO-PRELOAD-LABEL: v5f64_kernel_preload_arg: ; GFX940-NO-PRELOAD: ; %bb.0: ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x60 ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx8 s[4:11], s[0:1], 0x40 @@ -1718,30 +1052,7 @@ define amdgpu_kernel void @v5f64_arg(ptr addrspace(1) nocapture %out, <5 x doubl ; GFX940-NO-PRELOAD-NEXT: global_store_dwordx4 v4, v[0:3], s[12:13] sc0 sc1 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: v5f64_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dwordx2 s[12:13], s[0:1], 0x60 -; GFX940-PRELOAD-1-NEXT: s_load_dwordx8 s[4:11], s[0:1], 0x40 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v4, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: v_mov_b64_e32 v[2:3], s[12:13] -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, s8 -; GFX940-PRELOAD-1-NEXT: global_store_dwordx2 v4, v[2:3], s[2:3] offset:32 sc0 sc1 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s9 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s10 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v3, s11 -; GFX940-PRELOAD-1-NEXT: global_store_dwordx4 v4, v[0:3], s[2:3] offset:16 sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_nop 1 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, s4 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s5 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s6 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v3, s7 -; GFX940-PRELOAD-1-NEXT: global_store_dwordx4 v4, v[0:3], s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_endpgm -; -; GFX940-PRELOAD-2-LABEL: v5f64_arg: +; GFX940-PRELOAD-2-LABEL: v5f64_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: @@ -1764,30 +1075,7 @@ define amdgpu_kernel void @v5f64_arg(ptr addrspace(1) nocapture %out, <5 x doubl ; GFX940-PRELOAD-2-NEXT: global_store_dwordx4 v4, v[0:3], s[2:3] sc0 sc1 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: v5f64_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: s_load_dwordx2 s[12:13], s[0:1], 0x60 -; GFX940-PRELOAD-4-NEXT: s_load_dwordx8 s[4:11], s[0:1], 0x40 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v4, 0 -; GFX940-PRELOAD-4-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-4-NEXT: v_mov_b64_e32 v[2:3], s[12:13] -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, s8 -; GFX940-PRELOAD-4-NEXT: global_store_dwordx2 v4, v[2:3], s[2:3] offset:32 sc0 sc1 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s9 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v2, s10 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v3, s11 -; GFX940-PRELOAD-4-NEXT: global_store_dwordx4 v4, v[0:3], s[2:3] offset:16 sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_nop 1 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, s4 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s5 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v2, s6 -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v3, s7 -; GFX940-PRELOAD-4-NEXT: global_store_dwordx4 v4, v[0:3], s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_endpgm -; -; GFX940-PRELOAD-8-LABEL: v5f64_arg: +; GFX940-PRELOAD-8-LABEL: v5f64_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: @@ -1810,7 +1098,7 @@ define amdgpu_kernel void @v5f64_arg(ptr addrspace(1) nocapture %out, <5 x doubl ; GFX940-PRELOAD-8-NEXT: global_store_dwordx4 v4, v[0:3], s[2:3] sc0 sc1 ; GFX940-PRELOAD-8-NEXT: s_endpgm ; -; GFX90a-NO-PRELOAD-LABEL: v5f64_arg: +; GFX90a-NO-PRELOAD-LABEL: v5f64_kernel_preload_arg: ; GFX90a-NO-PRELOAD: ; %bb.0: ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x60 ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx8 s[8:15], s[4:5], 0x40 @@ -1832,30 +1120,7 @@ define amdgpu_kernel void @v5f64_arg(ptr addrspace(1) nocapture %out, <5 x doubl ; GFX90a-NO-PRELOAD-NEXT: global_store_dwordx4 v4, v[0:3], s[2:3] ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: v5f64_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x60 -; GFX90a-PRELOAD-1-NEXT: s_load_dwordx8 s[8:15], s[4:5], 0x40 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v4, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: v_pk_mov_b32 v[2:3], s[0:1], s[0:1] op_sel:[0,1] -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, s12 -; GFX90a-PRELOAD-1-NEXT: global_store_dwordx2 v4, v[2:3], s[6:7] offset:32 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s13 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s14 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v3, s15 -; GFX90a-PRELOAD-1-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] offset:16 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, s8 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v1, s9 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v2, s10 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v3, s11 -; GFX90a-PRELOAD-1-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; -; GFX90a-PRELOAD-2-LABEL: v5f64_arg: +; GFX90a-PRELOAD-2-LABEL: v5f64_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: @@ -1878,30 +1143,7 @@ define amdgpu_kernel void @v5f64_arg(ptr addrspace(1) nocapture %out, <5 x doubl ; GFX90a-PRELOAD-2-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: v5f64_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x60 -; GFX90a-PRELOAD-4-NEXT: s_load_dwordx8 s[8:15], s[4:5], 0x40 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v4, 0 -; GFX90a-PRELOAD-4-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-4-NEXT: v_pk_mov_b32 v[2:3], s[0:1], s[0:1] op_sel:[0,1] -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, s12 -; GFX90a-PRELOAD-4-NEXT: global_store_dwordx2 v4, v[2:3], s[6:7] offset:32 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s13 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v2, s14 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v3, s15 -; GFX90a-PRELOAD-4-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] offset:16 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, s8 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s9 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v2, s10 -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v3, s11 -; GFX90a-PRELOAD-4-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; -; GFX90a-PRELOAD-8-LABEL: v5f64_arg: +; GFX90a-PRELOAD-8-LABEL: v5f64_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: @@ -1927,8 +1169,8 @@ define amdgpu_kernel void @v5f64_arg(ptr addrspace(1) nocapture %out, <5 x doubl ret void } -define amdgpu_kernel void @v8i8_preload_arg(ptr addrspace(1) %out, <8 x i8> %in) { -; GFX940-NO-PRELOAD-LABEL: v8i8_preload_arg: +define amdgpu_kernel void @v8i8_kernel_preload_arg(ptr addrspace(1) %out, <8 x i8> %in) { +; GFX940-NO-PRELOAD-LABEL: v8i8_kernel_preload_arg: ; GFX940-NO-PRELOAD: ; %bb.0: ; GFX940-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 ; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v2, 0 @@ -1937,18 +1179,7 @@ define amdgpu_kernel void @v8i8_preload_arg(ptr addrspace(1) %out, <8 x i8> %in) ; GFX940-NO-PRELOAD-NEXT: global_store_dwordx2 v2, v[0:1], s[0:1] sc0 sc1 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: v8i8_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x8 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v2, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: v_mov_b64_e32 v[0:1], s[0:1] -; GFX940-PRELOAD-1-NEXT: global_store_dwordx2 v2, v[0:1], s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_endpgm -; -; GFX940-PRELOAD-2-LABEL: v8i8_preload_arg: +; GFX940-PRELOAD-2-LABEL: v8i8_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: @@ -1973,32 +1204,7 @@ define amdgpu_kernel void @v8i8_preload_arg(ptr addrspace(1) %out, <8 x i8> %in) ; GFX940-PRELOAD-2-NEXT: global_store_dwordx2 v2, v[0:1], s[2:3] sc0 sc1 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: v8i8_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: s_lshr_b32 s0, s5, 8 -; GFX940-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v0, 8, s0 -; GFX940-PRELOAD-4-NEXT: s_lshr_b32 s0, s5, 24 -; GFX940-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v1, 8, s0 -; GFX940-PRELOAD-4-NEXT: s_lshr_b32 s0, s5, 16 -; GFX940-PRELOAD-4-NEXT: v_or_b32_sdwa v0, s5, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX940-PRELOAD-4-NEXT: v_or_b32_sdwa v1, s0, v1 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX940-PRELOAD-4-NEXT: s_lshr_b32 s0, s4, 8 -; GFX940-PRELOAD-4-NEXT: v_or_b32_sdwa v1, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD -; GFX940-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v0, 8, s0 -; GFX940-PRELOAD-4-NEXT: s_lshr_b32 s0, s4, 24 -; GFX940-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v2, 8, s0 -; GFX940-PRELOAD-4-NEXT: s_lshr_b32 s0, s4, 16 -; GFX940-PRELOAD-4-NEXT: v_or_b32_sdwa v0, s4, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX940-PRELOAD-4-NEXT: v_or_b32_sdwa v2, s0, v2 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: v_or_b32_sdwa v0, v0, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v2, 0 -; GFX940-PRELOAD-4-NEXT: global_store_dwordx2 v2, v[0:1], s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_endpgm -; -; GFX940-PRELOAD-8-LABEL: v8i8_preload_arg: +; GFX940-PRELOAD-8-LABEL: v8i8_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: @@ -2023,7 +1229,7 @@ define amdgpu_kernel void @v8i8_preload_arg(ptr addrspace(1) %out, <8 x i8> %in) ; GFX940-PRELOAD-8-NEXT: global_store_dwordx2 v2, v[0:1], s[2:3] sc0 sc1 ; GFX940-PRELOAD-8-NEXT: s_endpgm ; -; GFX90a-NO-PRELOAD-LABEL: v8i8_preload_arg: +; GFX90a-NO-PRELOAD-LABEL: v8i8_kernel_preload_arg: ; GFX90a-NO-PRELOAD: ; %bb.0: ; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 ; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v2, 0 @@ -2032,18 +1238,7 @@ define amdgpu_kernel void @v8i8_preload_arg(ptr addrspace(1) %out, <8 x i8> %in) ; GFX90a-NO-PRELOAD-NEXT: global_store_dwordx2 v2, v[0:1], s[0:1] ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: v8i8_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x8 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v2, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: v_pk_mov_b32 v[0:1], s[0:1], s[0:1] op_sel:[0,1] -; GFX90a-PRELOAD-1-NEXT: global_store_dwordx2 v2, v[0:1], s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; -; GFX90a-PRELOAD-2-LABEL: v8i8_preload_arg: +; GFX90a-PRELOAD-2-LABEL: v8i8_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: @@ -2067,31 +1262,7 @@ define amdgpu_kernel void @v8i8_preload_arg(ptr addrspace(1) %out, <8 x i8> %in) ; GFX90a-PRELOAD-2-NEXT: global_store_dwordx2 v2, v[0:1], s[6:7] ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: v8i8_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: s_lshr_b32 s0, s9, 8 -; GFX90a-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v0, 8, s0 -; GFX90a-PRELOAD-4-NEXT: s_lshr_b32 s0, s9, 24 -; GFX90a-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v1, 8, s0 -; GFX90a-PRELOAD-4-NEXT: s_lshr_b32 s0, s9, 16 -; GFX90a-PRELOAD-4-NEXT: v_or_b32_sdwa v0, s9, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX90a-PRELOAD-4-NEXT: v_or_b32_sdwa v1, s0, v1 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX90a-PRELOAD-4-NEXT: s_lshr_b32 s0, s8, 8 -; GFX90a-PRELOAD-4-NEXT: v_or_b32_sdwa v1, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD -; GFX90a-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v0, 8, s0 -; GFX90a-PRELOAD-4-NEXT: s_lshr_b32 s0, s8, 24 -; GFX90a-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v2, 8, s0 -; GFX90a-PRELOAD-4-NEXT: s_lshr_b32 s0, s8, 16 -; GFX90a-PRELOAD-4-NEXT: v_or_b32_sdwa v0, s8, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX90a-PRELOAD-4-NEXT: v_or_b32_sdwa v2, s0, v2 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX90a-PRELOAD-4-NEXT: v_or_b32_sdwa v0, v0, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v2, 0 -; GFX90a-PRELOAD-4-NEXT: global_store_dwordx2 v2, v[0:1], s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; -; GFX90a-PRELOAD-8-LABEL: v8i8_preload_arg: +; GFX90a-PRELOAD-8-LABEL: v8i8_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: @@ -2129,17 +1300,6 @@ define amdgpu_kernel void @i64_kernel_preload_arg(ptr addrspace(1) %out, i64 %a) ; GFX940-NO-PRELOAD-NEXT: global_store_dwordx2 v2, v[0:1], s[0:1] sc0 sc1 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: i64_kernel_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x8 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v2, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: v_mov_b64_e32 v[0:1], s[0:1] -; GFX940-PRELOAD-1-NEXT: global_store_dwordx2 v2, v[0:1], s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_endpgm -; ; GFX940-PRELOAD-2-LABEL: i64_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 @@ -2149,15 +1309,6 @@ define amdgpu_kernel void @i64_kernel_preload_arg(ptr addrspace(1) %out, i64 %a) ; GFX940-PRELOAD-2-NEXT: global_store_dwordx2 v2, v[0:1], s[2:3] sc0 sc1 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: i64_kernel_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v2, 0 -; GFX940-PRELOAD-4-NEXT: v_mov_b64_e32 v[0:1], s[4:5] -; GFX940-PRELOAD-4-NEXT: global_store_dwordx2 v2, v[0:1], s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_endpgm -; ; GFX940-PRELOAD-8-LABEL: i64_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 @@ -2177,17 +1328,6 @@ define amdgpu_kernel void @i64_kernel_preload_arg(ptr addrspace(1) %out, i64 %a) ; GFX90a-NO-PRELOAD-NEXT: global_store_dwordx2 v2, v[0:1], s[0:1] ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: i64_kernel_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x8 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v2, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: v_pk_mov_b32 v[0:1], s[0:1], s[0:1] op_sel:[0,1] -; GFX90a-PRELOAD-1-NEXT: global_store_dwordx2 v2, v[0:1], s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; ; GFX90a-PRELOAD-2-LABEL: i64_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 @@ -2197,15 +1337,6 @@ define amdgpu_kernel void @i64_kernel_preload_arg(ptr addrspace(1) %out, i64 %a) ; GFX90a-PRELOAD-2-NEXT: global_store_dwordx2 v2, v[0:1], s[6:7] ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: i64_kernel_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v2, 0 -; GFX90a-PRELOAD-4-NEXT: v_pk_mov_b32 v[0:1], s[8:9], s[8:9] op_sel:[0,1] -; GFX90a-PRELOAD-4-NEXT: global_store_dwordx2 v2, v[0:1], s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; ; GFX90a-PRELOAD-8-LABEL: i64_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 @@ -2229,17 +1360,6 @@ define amdgpu_kernel void @f64_kernel_preload_arg(ptr addrspace(1) %out, double ; GFX940-NO-PRELOAD-NEXT: global_store_dwordx2 v2, v[0:1], s[0:1] sc0 sc1 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; -; GFX940-PRELOAD-1-LABEL: f64_kernel_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-1-NEXT: ; %bb.0: -; GFX940-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x8 -; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v2, 0 -; GFX940-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-PRELOAD-1-NEXT: v_mov_b64_e32 v[0:1], s[0:1] -; GFX940-PRELOAD-1-NEXT: global_store_dwordx2 v2, v[0:1], s[2:3] sc0 sc1 -; GFX940-PRELOAD-1-NEXT: s_endpgm -; ; GFX940-PRELOAD-2-LABEL: f64_kernel_preload_arg: ; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 @@ -2249,15 +1369,6 @@ define amdgpu_kernel void @f64_kernel_preload_arg(ptr addrspace(1) %out, double ; GFX940-PRELOAD-2-NEXT: global_store_dwordx2 v2, v[0:1], s[2:3] sc0 sc1 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; -; GFX940-PRELOAD-4-LABEL: f64_kernel_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX940-PRELOAD-4-NEXT: ; %bb.0: -; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v2, 0 -; GFX940-PRELOAD-4-NEXT: v_mov_b64_e32 v[0:1], s[4:5] -; GFX940-PRELOAD-4-NEXT: global_store_dwordx2 v2, v[0:1], s[2:3] sc0 sc1 -; GFX940-PRELOAD-4-NEXT: s_endpgm -; ; GFX940-PRELOAD-8-LABEL: f64_kernel_preload_arg: ; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 @@ -2277,17 +1388,6 @@ define amdgpu_kernel void @f64_kernel_preload_arg(ptr addrspace(1) %out, double ; GFX90a-NO-PRELOAD-NEXT: global_store_dwordx2 v2, v[0:1], s[0:1] ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; -; GFX90a-PRELOAD-1-LABEL: f64_kernel_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-1-NEXT: ; %bb.0: -; GFX90a-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x8 -; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v2, 0 -; GFX90a-PRELOAD-1-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-1-NEXT: v_pk_mov_b32 v[0:1], s[0:1], s[0:1] op_sel:[0,1] -; GFX90a-PRELOAD-1-NEXT: global_store_dwordx2 v2, v[0:1], s[6:7] -; GFX90a-PRELOAD-1-NEXT: s_endpgm -; ; GFX90a-PRELOAD-2-LABEL: f64_kernel_preload_arg: ; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 @@ -2297,15 +1397,6 @@ define amdgpu_kernel void @f64_kernel_preload_arg(ptr addrspace(1) %out, double ; GFX90a-PRELOAD-2-NEXT: global_store_dwordx2 v2, v[0:1], s[6:7] ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; -; GFX90a-PRELOAD-4-LABEL: f64_kernel_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 -; GFX90a-PRELOAD-4-NEXT: ; %bb.0: -; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v2, 0 -; GFX90a-PRELOAD-4-NEXT: v_pk_mov_b32 v[0:1], s[8:9], s[8:9] op_sel:[0,1] -; GFX90a-PRELOAD-4-NEXT: global_store_dwordx2 v2, v[0:1], s[6:7] -; GFX90a-PRELOAD-4-NEXT: s_endpgm -; ; GFX90a-PRELOAD-8-LABEL: f64_kernel_preload_arg: ; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. ; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 @@ -2317,3 +1408,1115 @@ define amdgpu_kernel void @f64_kernel_preload_arg(ptr addrspace(1) %out, double store double %in, ptr addrspace(1) %out ret void } + +define amdgpu_kernel void @half_kernel_preload_arg(ptr addrspace(1) %out, half %in) { +; GFX940-NO-PRELOAD-LABEL: half_kernel_preload_arg: +; GFX940-NO-PRELOAD: ; %bb.0: +; GFX940-NO-PRELOAD-NEXT: s_load_dword s4, s[0:1], 0x8 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s4 +; GFX940-NO-PRELOAD-NEXT: global_store_short v0, v1, s[2:3] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: s_endpgm +; +; GFX940-PRELOAD-2-LABEL: half_kernel_preload_arg: +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-2-NEXT: ; %bb.0: +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s4 +; GFX940-PRELOAD-2-NEXT: global_store_short v0, v1, s[2:3] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_endpgm +; +; GFX940-PRELOAD-8-LABEL: half_kernel_preload_arg: +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-8-NEXT: ; %bb.0: +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s4 +; GFX940-PRELOAD-8-NEXT: global_store_short v0, v1, s[2:3] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: s_endpgm +; +; GFX90a-NO-PRELOAD-LABEL: half_kernel_preload_arg: +; GFX90a-NO-PRELOAD: ; %bb.0: +; GFX90a-NO-PRELOAD-NEXT: s_load_dword s2, s[4:5], 0x8 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s2 +; GFX90a-NO-PRELOAD-NEXT: global_store_short v0, v1, s[0:1] +; GFX90a-NO-PRELOAD-NEXT: s_endpgm +; +; GFX90a-PRELOAD-2-LABEL: half_kernel_preload_arg: +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-2-NEXT: ; %bb.0: +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s8 +; GFX90a-PRELOAD-2-NEXT: global_store_short v0, v1, s[6:7] +; GFX90a-PRELOAD-2-NEXT: s_endpgm +; +; GFX90a-PRELOAD-8-LABEL: half_kernel_preload_arg: +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-8-NEXT: ; %bb.0: +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s8 +; GFX90a-PRELOAD-8-NEXT: global_store_short v0, v1, s[6:7] +; GFX90a-PRELOAD-8-NEXT: s_endpgm + store half %in, ptr addrspace(1) %out + ret void +} + +define amdgpu_kernel void @bfloat_kernel_preload_arg(ptr addrspace(1) %out, bfloat %in) { +; GFX940-NO-PRELOAD-LABEL: bfloat_kernel_preload_arg: +; GFX940-NO-PRELOAD: ; %bb.0: +; GFX940-NO-PRELOAD-NEXT: s_load_dword s4, s[0:1], 0x8 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s4 +; GFX940-NO-PRELOAD-NEXT: global_store_short v0, v1, s[2:3] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: s_endpgm +; +; GFX940-PRELOAD-2-LABEL: bfloat_kernel_preload_arg: +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-2-NEXT: ; %bb.0: +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s4 +; GFX940-PRELOAD-2-NEXT: global_store_short v0, v1, s[2:3] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_endpgm +; +; GFX940-PRELOAD-8-LABEL: bfloat_kernel_preload_arg: +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-8-NEXT: ; %bb.0: +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s4 +; GFX940-PRELOAD-8-NEXT: global_store_short v0, v1, s[2:3] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: s_endpgm +; +; GFX90a-NO-PRELOAD-LABEL: bfloat_kernel_preload_arg: +; GFX90a-NO-PRELOAD: ; %bb.0: +; GFX90a-NO-PRELOAD-NEXT: s_load_dword s2, s[4:5], 0x8 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s2 +; GFX90a-NO-PRELOAD-NEXT: global_store_short v0, v1, s[0:1] +; GFX90a-NO-PRELOAD-NEXT: s_endpgm +; +; GFX90a-PRELOAD-2-LABEL: bfloat_kernel_preload_arg: +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-2-NEXT: ; %bb.0: +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s8 +; GFX90a-PRELOAD-2-NEXT: global_store_short v0, v1, s[6:7] +; GFX90a-PRELOAD-2-NEXT: s_endpgm +; +; GFX90a-PRELOAD-8-LABEL: bfloat_kernel_preload_arg: +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-8-NEXT: ; %bb.0: +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s8 +; GFX90a-PRELOAD-8-NEXT: global_store_short v0, v1, s[6:7] +; GFX90a-PRELOAD-8-NEXT: s_endpgm + store bfloat %in, ptr addrspace(1) %out + ret void +} + +define amdgpu_kernel void @v2bfloat_kernel_preload_arg(ptr addrspace(1) %out, <2 x bfloat> %in) { +; GFX940-NO-PRELOAD-LABEL: v2bfloat_kernel_preload_arg: +; GFX940-NO-PRELOAD: ; %bb.0: +; GFX940-NO-PRELOAD-NEXT: s_load_dword s4, s[0:1], 0x8 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s4 +; GFX940-NO-PRELOAD-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: s_endpgm +; +; GFX940-PRELOAD-2-LABEL: v2bfloat_kernel_preload_arg: +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-2-NEXT: ; %bb.0: +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s4 +; GFX940-PRELOAD-2-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_endpgm +; +; GFX940-PRELOAD-8-LABEL: v2bfloat_kernel_preload_arg: +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-8-NEXT: ; %bb.0: +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s4 +; GFX940-PRELOAD-8-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: s_endpgm +; +; GFX90a-NO-PRELOAD-LABEL: v2bfloat_kernel_preload_arg: +; GFX90a-NO-PRELOAD: ; %bb.0: +; GFX90a-NO-PRELOAD-NEXT: s_load_dword s2, s[4:5], 0x8 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s2 +; GFX90a-NO-PRELOAD-NEXT: global_store_dword v0, v1, s[0:1] +; GFX90a-NO-PRELOAD-NEXT: s_endpgm +; +; GFX90a-PRELOAD-2-LABEL: v2bfloat_kernel_preload_arg: +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-2-NEXT: ; %bb.0: +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s8 +; GFX90a-PRELOAD-2-NEXT: global_store_dword v0, v1, s[6:7] +; GFX90a-PRELOAD-2-NEXT: s_endpgm +; +; GFX90a-PRELOAD-8-LABEL: v2bfloat_kernel_preload_arg: +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-8-NEXT: ; %bb.0: +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s8 +; GFX90a-PRELOAD-8-NEXT: global_store_dword v0, v1, s[6:7] +; GFX90a-PRELOAD-8-NEXT: s_endpgm + store <2 x bfloat> %in, ptr addrspace(1) %out + ret void +} + +define amdgpu_kernel void @v3bfloat_kernel_preload_arg(ptr addrspace(1) %out, <3 x bfloat> %in) { +; GFX940-NO-PRELOAD-LABEL: v3bfloat_kernel_preload_arg: +; GFX940-NO-PRELOAD: ; %bb.0: +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s3 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v2, s2 +; GFX940-NO-PRELOAD-NEXT: global_store_short v0, v1, s[0:1] offset:4 sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: global_store_dword v0, v2, s[0:1] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: s_endpgm +; +; GFX940-PRELOAD-2-LABEL: v3bfloat_kernel_preload_arg: +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-2-NEXT: ; %bb.0: +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s5 +; GFX940-PRELOAD-2-NEXT: global_store_short v0, v1, s[2:3] offset:4 sc0 sc1 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s4 +; GFX940-PRELOAD-2-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_endpgm +; +; GFX940-PRELOAD-8-LABEL: v3bfloat_kernel_preload_arg: +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-8-NEXT: ; %bb.0: +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s5 +; GFX940-PRELOAD-8-NEXT: global_store_short v0, v1, s[2:3] offset:4 sc0 sc1 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s4 +; GFX940-PRELOAD-8-NEXT: global_store_dword v0, v1, s[2:3] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: s_endpgm +; +; GFX90a-NO-PRELOAD-LABEL: v3bfloat_kernel_preload_arg: +; GFX90a-NO-PRELOAD: ; %bb.0: +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s3 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v2, s2 +; GFX90a-NO-PRELOAD-NEXT: global_store_short v0, v1, s[0:1] offset:4 +; GFX90a-NO-PRELOAD-NEXT: global_store_dword v0, v2, s[0:1] +; GFX90a-NO-PRELOAD-NEXT: s_endpgm +; +; GFX90a-PRELOAD-2-LABEL: v3bfloat_kernel_preload_arg: +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-2-NEXT: ; %bb.0: +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s9 +; GFX90a-PRELOAD-2-NEXT: global_store_short v0, v1, s[6:7] offset:4 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s8 +; GFX90a-PRELOAD-2-NEXT: global_store_dword v0, v1, s[6:7] +; GFX90a-PRELOAD-2-NEXT: s_endpgm +; +; GFX90a-PRELOAD-8-LABEL: v3bfloat_kernel_preload_arg: +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-8-NEXT: ; %bb.0: +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s9 +; GFX90a-PRELOAD-8-NEXT: global_store_short v0, v1, s[6:7] offset:4 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s8 +; GFX90a-PRELOAD-8-NEXT: global_store_dword v0, v1, s[6:7] +; GFX90a-PRELOAD-8-NEXT: s_endpgm + store <3 x bfloat> %in, ptr addrspace(1) %out + ret void +} + +define amdgpu_kernel void @v6bfloat_kernel_preload_arg(ptr addrspace(1) %out, <6 x bfloat> %in) { +; GFX940-NO-PRELOAD-LABEL: v6bfloat_kernel_preload_arg: +; GFX940-NO-PRELOAD: ; %bb.0: +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x10 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v3, 0 +; GFX940-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, s4 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s5 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v2, s6 +; GFX940-NO-PRELOAD-NEXT: global_store_dwordx3 v3, v[0:2], s[2:3] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: s_endpgm +; +; GFX940-PRELOAD-2-LABEL: v6bfloat_kernel_preload_arg: +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-2-NEXT: ; %bb.0: +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s6 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s7 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v2, s8 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v3, 0 +; GFX940-PRELOAD-2-NEXT: global_store_dwordx3 v3, v[0:2], s[2:3] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_endpgm +; +; GFX940-PRELOAD-8-LABEL: v6bfloat_kernel_preload_arg: +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-8-NEXT: ; %bb.0: +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s6 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s7 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v2, s8 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v3, 0 +; GFX940-PRELOAD-8-NEXT: global_store_dwordx3 v3, v[0:2], s[2:3] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: s_endpgm +; +; GFX90a-NO-PRELOAD-LABEL: v6bfloat_kernel_preload_arg: +; GFX90a-NO-PRELOAD: ; %bb.0: +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x10 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[6:7], s[4:5], 0x0 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v3, 0 +; GFX90a-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, s0 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s1 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v2, s2 +; GFX90a-NO-PRELOAD-NEXT: global_store_dwordx3 v3, v[0:2], s[6:7] +; GFX90a-NO-PRELOAD-NEXT: s_endpgm +; +; GFX90a-PRELOAD-2-LABEL: v6bfloat_kernel_preload_arg: +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-2-NEXT: ; %bb.0: +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s10 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s11 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v2, s12 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v3, 0 +; GFX90a-PRELOAD-2-NEXT: global_store_dwordx3 v3, v[0:2], s[6:7] +; GFX90a-PRELOAD-2-NEXT: s_endpgm +; +; GFX90a-PRELOAD-8-LABEL: v6bfloat_kernel_preload_arg: +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-8-NEXT: ; %bb.0: +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s10 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s11 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v2, s12 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v3, 0 +; GFX90a-PRELOAD-8-NEXT: global_store_dwordx3 v3, v[0:2], s[6:7] +; GFX90a-PRELOAD-8-NEXT: s_endpgm + store <6 x bfloat> %in, ptr addrspace(1) %out + ret void +} + +define amdgpu_kernel void @half_v7bfloat_kernel_preload_arg(ptr addrspace(1) %out, half %in, <7 x bfloat> %in2, ptr addrspace(1) %out2) { +; GFX940-NO-PRELOAD-LABEL: half_v7bfloat_kernel_preload_arg: +; GFX940-NO-PRELOAD: ; %bb.0: +; GFX940-NO-PRELOAD-NEXT: s_load_dword s10, s[0:1], 0x8 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x10 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[8:9], s[0:1], 0x20 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v3, 0 +; GFX940-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, s10 +; GFX940-NO-PRELOAD-NEXT: global_store_short v3, v0, s[2:3] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, s7 +; GFX940-NO-PRELOAD-NEXT: global_store_short v3, v0, s[8:9] offset:12 sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v2, s6 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, s4 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s5 +; GFX940-NO-PRELOAD-NEXT: global_store_dwordx3 v3, v[0:2], s[8:9] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: s_endpgm +; +; GFX940-PRELOAD-2-LABEL: half_v7bfloat_kernel_preload_arg: +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-2-NEXT: ; %bb.0: +; GFX940-PRELOAD-2-NEXT: s_load_dwordx4 s[8:11], s[0:1], 0x10 +; GFX940-PRELOAD-2-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x20 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v3, 0 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s4 +; GFX940-PRELOAD-2-NEXT: global_store_short v3, v0, s[2:3] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s11 +; GFX940-PRELOAD-2-NEXT: global_store_short v3, v0, s[6:7] offset:12 sc0 sc1 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v2, s10 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s8 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s9 +; GFX940-PRELOAD-2-NEXT: global_store_dwordx3 v3, v[0:2], s[6:7] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_endpgm +; +; GFX940-PRELOAD-8-LABEL: half_v7bfloat_kernel_preload_arg: +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-8-NEXT: ; %bb.0: +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v3, 0 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s4 +; GFX940-PRELOAD-8-NEXT: global_store_short v3, v0, s[2:3] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s9 +; GFX940-PRELOAD-8-NEXT: global_store_short v3, v0, s[10:11] offset:12 sc0 sc1 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v2, s8 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s6 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s7 +; GFX940-PRELOAD-8-NEXT: global_store_dwordx3 v3, v[0:2], s[10:11] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: s_endpgm +; +; GFX90a-NO-PRELOAD-LABEL: half_v7bfloat_kernel_preload_arg: +; GFX90a-NO-PRELOAD: ; %bb.0: +; GFX90a-NO-PRELOAD-NEXT: s_load_dword s10, s[4:5], 0x8 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[6:7], s[4:5], 0x0 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x10 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[8:9], s[4:5], 0x20 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v3, 0 +; GFX90a-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, s10 +; GFX90a-NO-PRELOAD-NEXT: global_store_short v3, v0, s[6:7] +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, s3 +; GFX90a-NO-PRELOAD-NEXT: global_store_short v3, v0, s[8:9] offset:12 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v2, s2 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, s0 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s1 +; GFX90a-NO-PRELOAD-NEXT: global_store_dwordx3 v3, v[0:2], s[8:9] +; GFX90a-NO-PRELOAD-NEXT: s_endpgm +; +; GFX90a-PRELOAD-2-LABEL: half_v7bfloat_kernel_preload_arg: +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-2-NEXT: ; %bb.0: +; GFX90a-PRELOAD-2-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x10 +; GFX90a-PRELOAD-2-NEXT: s_load_dwordx2 s[10:11], s[4:5], 0x20 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v3, 0 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s8 +; GFX90a-PRELOAD-2-NEXT: global_store_short v3, v0, s[6:7] +; GFX90a-PRELOAD-2-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s3 +; GFX90a-PRELOAD-2-NEXT: global_store_short v3, v0, s[10:11] offset:12 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v2, s2 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s0 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s1 +; GFX90a-PRELOAD-2-NEXT: global_store_dwordx3 v3, v[0:2], s[10:11] +; GFX90a-PRELOAD-2-NEXT: s_endpgm +; +; GFX90a-PRELOAD-8-LABEL: half_v7bfloat_kernel_preload_arg: +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-8-NEXT: ; %bb.0: +; GFX90a-PRELOAD-8-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x20 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v3, 0 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s8 +; GFX90a-PRELOAD-8-NEXT: global_store_short v3, v0, s[6:7] +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s13 +; GFX90a-PRELOAD-8-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-PRELOAD-8-NEXT: global_store_short v3, v0, s[0:1] offset:12 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v2, s12 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s10 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s11 +; GFX90a-PRELOAD-8-NEXT: global_store_dwordx3 v3, v[0:2], s[0:1] +; GFX90a-PRELOAD-8-NEXT: s_endpgm + store half %in, ptr addrspace(1) %out + store <7 x bfloat> %in2, ptr addrspace(1) %out2 + ret void +} + +define amdgpu_kernel void @i1_kernel_preload_arg(ptr addrspace(1) %out, i1 %in) { +; GFX940-NO-PRELOAD-LABEL: i1_kernel_preload_arg: +; GFX940-NO-PRELOAD: ; %bb.0: +; GFX940-NO-PRELOAD-NEXT: s_load_dword s4, s[0:1], 0x8 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NO-PRELOAD-NEXT: s_and_b32 s0, s4, 1 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s0 +; GFX940-NO-PRELOAD-NEXT: global_store_byte v0, v1, s[2:3] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: s_endpgm +; +; GFX940-PRELOAD-2-LABEL: i1_kernel_preload_arg: +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-2-NEXT: ; %bb.0: +; GFX940-PRELOAD-2-NEXT: s_and_b32 s0, s4, 1 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s0 +; GFX940-PRELOAD-2-NEXT: global_store_byte v0, v1, s[2:3] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_endpgm +; +; GFX940-PRELOAD-8-LABEL: i1_kernel_preload_arg: +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-8-NEXT: ; %bb.0: +; GFX940-PRELOAD-8-NEXT: s_and_b32 s0, s4, 1 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s0 +; GFX940-PRELOAD-8-NEXT: global_store_byte v0, v1, s[2:3] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: s_endpgm +; +; GFX90a-NO-PRELOAD-LABEL: i1_kernel_preload_arg: +; GFX90a-NO-PRELOAD: ; %bb.0: +; GFX90a-NO-PRELOAD-NEXT: s_load_dword s2, s[4:5], 0x8 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-NO-PRELOAD-NEXT: s_and_b32 s2, s2, 1 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s2 +; GFX90a-NO-PRELOAD-NEXT: global_store_byte v0, v1, s[0:1] +; GFX90a-NO-PRELOAD-NEXT: s_endpgm +; +; GFX90a-PRELOAD-2-LABEL: i1_kernel_preload_arg: +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-2-NEXT: ; %bb.0: +; GFX90a-PRELOAD-2-NEXT: s_and_b32 s0, s8, 1 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s0 +; GFX90a-PRELOAD-2-NEXT: global_store_byte v0, v1, s[6:7] +; GFX90a-PRELOAD-2-NEXT: s_endpgm +; +; GFX90a-PRELOAD-8-LABEL: i1_kernel_preload_arg: +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-8-NEXT: ; %bb.0: +; GFX90a-PRELOAD-8-NEXT: s_and_b32 s0, s8, 1 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s0 +; GFX90a-PRELOAD-8-NEXT: global_store_byte v0, v1, s[6:7] +; GFX90a-PRELOAD-8-NEXT: s_endpgm + store i1 %in, ptr addrspace(1) %out + ret void +} + +define amdgpu_kernel void @fp128_kernel_preload_arg(ptr addrspace(1) %out, fp128 %in) { +; GFX940-NO-PRELOAD-LABEL: fp128_kernel_preload_arg: +; GFX940-NO-PRELOAD: ; %bb.0: +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x10 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v4, 0 +; GFX940-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NO-PRELOAD-NEXT: v_mov_b64_e32 v[0:1], s[4:5] +; GFX940-NO-PRELOAD-NEXT: v_mov_b64_e32 v[2:3], s[6:7] +; GFX940-NO-PRELOAD-NEXT: global_store_dwordx4 v4, v[0:3], s[2:3] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: s_endpgm +; +; GFX940-PRELOAD-2-LABEL: fp128_kernel_preload_arg: +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-2-NEXT: ; %bb.0: +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v4, 0 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s6 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s7 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v2, s8 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v3, s9 +; GFX940-PRELOAD-2-NEXT: global_store_dwordx4 v4, v[0:3], s[2:3] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_endpgm +; +; GFX940-PRELOAD-8-LABEL: fp128_kernel_preload_arg: +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-8-NEXT: ; %bb.0: +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v4, 0 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s6 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s7 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v2, s8 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v3, s9 +; GFX940-PRELOAD-8-NEXT: global_store_dwordx4 v4, v[0:3], s[2:3] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: s_endpgm +; +; GFX90a-NO-PRELOAD-LABEL: fp128_kernel_preload_arg: +; GFX90a-NO-PRELOAD: ; %bb.0: +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x10 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[6:7], s[4:5], 0x0 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v4, 0 +; GFX90a-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-NO-PRELOAD-NEXT: v_pk_mov_b32 v[0:1], s[0:1], s[0:1] op_sel:[0,1] +; GFX90a-NO-PRELOAD-NEXT: v_pk_mov_b32 v[2:3], s[2:3], s[2:3] op_sel:[0,1] +; GFX90a-NO-PRELOAD-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] +; GFX90a-NO-PRELOAD-NEXT: s_endpgm +; +; GFX90a-PRELOAD-2-LABEL: fp128_kernel_preload_arg: +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-2-NEXT: ; %bb.0: +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v4, 0 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s10 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s11 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v2, s12 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v3, s13 +; GFX90a-PRELOAD-2-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] +; GFX90a-PRELOAD-2-NEXT: s_endpgm +; +; GFX90a-PRELOAD-8-LABEL: fp128_kernel_preload_arg: +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-8-NEXT: ; %bb.0: +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v4, 0 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s10 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s11 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v2, s12 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v3, s13 +; GFX90a-PRELOAD-8-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] +; GFX90a-PRELOAD-8-NEXT: s_endpgm + store fp128 %in, ptr addrspace(1) %out + ret void +} + +define amdgpu_kernel void @v7i8_kernel_preload_arg(ptr addrspace(1) %out, <7 x i8> %in) { +; GFX940-NO-PRELOAD-LABEL: v7i8_kernel_preload_arg: +; GFX940-NO-PRELOAD: ; %bb.0: +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s3 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v2, s2 +; GFX940-NO-PRELOAD-NEXT: global_store_byte_d16_hi v0, v1, s[0:1] offset:6 sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: global_store_short v0, v1, s[0:1] offset:4 sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: global_store_dword v0, v2, s[0:1] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: s_endpgm +; +; GFX940-PRELOAD-2-LABEL: v7i8_kernel_preload_arg: +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-2-NEXT: ; %bb.0: +; GFX940-PRELOAD-2-NEXT: s_lshr_b32 s0, s4, 8 +; GFX940-PRELOAD-2-NEXT: v_lshlrev_b16_e64 v0, 8, s0 +; GFX940-PRELOAD-2-NEXT: s_lshr_b32 s0, s4, 24 +; GFX940-PRELOAD-2-NEXT: v_lshlrev_b16_e64 v1, 8, s0 +; GFX940-PRELOAD-2-NEXT: s_lshr_b32 s0, s4, 16 +; GFX940-PRELOAD-2-NEXT: v_or_b32_sdwa v0, s4, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX940-PRELOAD-2-NEXT: v_or_b32_sdwa v1, s0, v1 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX940-PRELOAD-2-NEXT: s_lshr_b32 s0, s5, 8 +; GFX940-PRELOAD-2-NEXT: v_or_b32_sdwa v0, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; GFX940-PRELOAD-2-NEXT: v_lshlrev_b16_e64 v1, 8, s0 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v2, 0 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v3, s5 +; GFX940-PRELOAD-2-NEXT: v_or_b32_sdwa v1, s5, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX940-PRELOAD-2-NEXT: global_store_byte_d16_hi v2, v3, s[2:3] offset:6 sc0 sc1 +; GFX940-PRELOAD-2-NEXT: global_store_short v2, v1, s[2:3] offset:4 sc0 sc1 +; GFX940-PRELOAD-2-NEXT: global_store_dword v2, v0, s[2:3] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_endpgm +; +; GFX940-PRELOAD-8-LABEL: v7i8_kernel_preload_arg: +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-8-NEXT: ; %bb.0: +; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s4, 8 +; GFX940-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v0, 8, s0 +; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s4, 24 +; GFX940-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v1, 8, s0 +; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s4, 16 +; GFX940-PRELOAD-8-NEXT: v_or_b32_sdwa v0, s4, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX940-PRELOAD-8-NEXT: v_or_b32_sdwa v1, s0, v1 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s5, 8 +; GFX940-PRELOAD-8-NEXT: v_or_b32_sdwa v0, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; GFX940-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v1, 8, s0 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v2, 0 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v3, s5 +; GFX940-PRELOAD-8-NEXT: v_or_b32_sdwa v1, s5, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX940-PRELOAD-8-NEXT: global_store_byte_d16_hi v2, v3, s[2:3] offset:6 sc0 sc1 +; GFX940-PRELOAD-8-NEXT: global_store_short v2, v1, s[2:3] offset:4 sc0 sc1 +; GFX940-PRELOAD-8-NEXT: global_store_dword v2, v0, s[2:3] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: s_endpgm +; +; GFX90a-NO-PRELOAD-LABEL: v7i8_kernel_preload_arg: +; GFX90a-NO-PRELOAD: ; %bb.0: +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s3 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v2, s2 +; GFX90a-NO-PRELOAD-NEXT: global_store_byte_d16_hi v0, v1, s[0:1] offset:6 +; GFX90a-NO-PRELOAD-NEXT: global_store_short v0, v1, s[0:1] offset:4 +; GFX90a-NO-PRELOAD-NEXT: global_store_dword v0, v2, s[0:1] +; GFX90a-NO-PRELOAD-NEXT: s_endpgm +; +; GFX90a-PRELOAD-2-LABEL: v7i8_kernel_preload_arg: +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-2-NEXT: ; %bb.0: +; GFX90a-PRELOAD-2-NEXT: s_lshr_b32 s0, s8, 8 +; GFX90a-PRELOAD-2-NEXT: v_lshlrev_b16_e64 v0, 8, s0 +; GFX90a-PRELOAD-2-NEXT: s_lshr_b32 s0, s8, 24 +; GFX90a-PRELOAD-2-NEXT: v_lshlrev_b16_e64 v1, 8, s0 +; GFX90a-PRELOAD-2-NEXT: s_lshr_b32 s0, s8, 16 +; GFX90a-PRELOAD-2-NEXT: v_or_b32_sdwa v0, s8, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX90a-PRELOAD-2-NEXT: v_or_b32_sdwa v1, s0, v1 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX90a-PRELOAD-2-NEXT: s_lshr_b32 s0, s9, 8 +; GFX90a-PRELOAD-2-NEXT: v_or_b32_sdwa v0, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; GFX90a-PRELOAD-2-NEXT: v_lshlrev_b16_e64 v1, 8, s0 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v2, 0 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v3, s9 +; GFX90a-PRELOAD-2-NEXT: v_or_b32_sdwa v1, s9, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX90a-PRELOAD-2-NEXT: global_store_byte_d16_hi v2, v3, s[6:7] offset:6 +; GFX90a-PRELOAD-2-NEXT: global_store_short v2, v1, s[6:7] offset:4 +; GFX90a-PRELOAD-2-NEXT: global_store_dword v2, v0, s[6:7] +; GFX90a-PRELOAD-2-NEXT: s_endpgm +; +; GFX90a-PRELOAD-8-LABEL: v7i8_kernel_preload_arg: +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-8-NEXT: ; %bb.0: +; GFX90a-PRELOAD-8-NEXT: s_lshr_b32 s0, s8, 8 +; GFX90a-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v0, 8, s0 +; GFX90a-PRELOAD-8-NEXT: s_lshr_b32 s0, s8, 24 +; GFX90a-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v1, 8, s0 +; GFX90a-PRELOAD-8-NEXT: s_lshr_b32 s0, s8, 16 +; GFX90a-PRELOAD-8-NEXT: v_or_b32_sdwa v0, s8, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX90a-PRELOAD-8-NEXT: v_or_b32_sdwa v1, s0, v1 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX90a-PRELOAD-8-NEXT: s_lshr_b32 s0, s9, 8 +; GFX90a-PRELOAD-8-NEXT: v_or_b32_sdwa v0, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; GFX90a-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v1, 8, s0 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v2, 0 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v3, s9 +; GFX90a-PRELOAD-8-NEXT: v_or_b32_sdwa v1, s9, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX90a-PRELOAD-8-NEXT: global_store_byte_d16_hi v2, v3, s[6:7] offset:6 +; GFX90a-PRELOAD-8-NEXT: global_store_short v2, v1, s[6:7] offset:4 +; GFX90a-PRELOAD-8-NEXT: global_store_dword v2, v0, s[6:7] +; GFX90a-PRELOAD-8-NEXT: s_endpgm + store <7 x i8> %in, ptr addrspace(1) %out + ret void +} + +define amdgpu_kernel void @v7half_kernel_preload_arg(ptr addrspace(1) %out, <7 x half> %in) { +; GFX940-NO-PRELOAD-LABEL: v7half_kernel_preload_arg: +; GFX940-NO-PRELOAD: ; %bb.0: +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x10 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v3, 0 +; GFX940-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s7 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v2, s6 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, s4 +; GFX940-NO-PRELOAD-NEXT: global_store_short v3, v1, s[2:3] offset:12 sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s5 +; GFX940-NO-PRELOAD-NEXT: global_store_dwordx3 v3, v[0:2], s[2:3] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: s_endpgm +; +; GFX940-PRELOAD-2-LABEL: v7half_kernel_preload_arg: +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-2-NEXT: ; %bb.0: +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v3, 0 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s9 +; GFX940-PRELOAD-2-NEXT: global_store_short v3, v0, s[2:3] offset:12 sc0 sc1 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v2, s8 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s6 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s7 +; GFX940-PRELOAD-2-NEXT: global_store_dwordx3 v3, v[0:2], s[2:3] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_endpgm +; +; GFX940-PRELOAD-8-LABEL: v7half_kernel_preload_arg: +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-8-NEXT: ; %bb.0: +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v3, 0 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s9 +; GFX940-PRELOAD-8-NEXT: global_store_short v3, v0, s[2:3] offset:12 sc0 sc1 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v2, s8 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s6 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s7 +; GFX940-PRELOAD-8-NEXT: global_store_dwordx3 v3, v[0:2], s[2:3] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: s_endpgm +; +; GFX90a-NO-PRELOAD-LABEL: v7half_kernel_preload_arg: +; GFX90a-NO-PRELOAD: ; %bb.0: +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x10 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[6:7], s[4:5], 0x0 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v3, 0 +; GFX90a-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s3 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v2, s2 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, s0 +; GFX90a-NO-PRELOAD-NEXT: global_store_short v3, v1, s[6:7] offset:12 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s1 +; GFX90a-NO-PRELOAD-NEXT: global_store_dwordx3 v3, v[0:2], s[6:7] +; GFX90a-NO-PRELOAD-NEXT: s_endpgm +; +; GFX90a-PRELOAD-2-LABEL: v7half_kernel_preload_arg: +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-2-NEXT: ; %bb.0: +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v3, 0 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s13 +; GFX90a-PRELOAD-2-NEXT: global_store_short v3, v0, s[6:7] offset:12 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v2, s12 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s10 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s11 +; GFX90a-PRELOAD-2-NEXT: global_store_dwordx3 v3, v[0:2], s[6:7] +; GFX90a-PRELOAD-2-NEXT: s_endpgm +; +; GFX90a-PRELOAD-8-LABEL: v7half_kernel_preload_arg: +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-8-NEXT: ; %bb.0: +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v3, 0 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s13 +; GFX90a-PRELOAD-8-NEXT: global_store_short v3, v0, s[6:7] offset:12 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v2, s12 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s10 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s11 +; GFX90a-PRELOAD-8-NEXT: global_store_dwordx3 v3, v[0:2], s[6:7] +; GFX90a-PRELOAD-8-NEXT: s_endpgm + store <7 x half> %in, ptr addrspace(1) %out + ret void +} + +; Test when previous argument was not dword aligned. +define amdgpu_kernel void @i16_i32_kernel_preload_arg(ptr addrspace(1) %out, i16 %in, i32 %in2, ptr addrspace(1) %out2) { +; GFX940-NO-PRELOAD-LABEL: i16_i32_kernel_preload_arg: +; GFX940-NO-PRELOAD: ; %bb.0: +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x0 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x10 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s6 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v2, s7 +; GFX940-NO-PRELOAD-NEXT: global_store_short v0, v1, s[4:5] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: global_store_dword v0, v2, s[2:3] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: s_endpgm +; +; GFX940-PRELOAD-2-LABEL: i16_i32_kernel_preload_arg: +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-2-NEXT: ; %bb.0: +; GFX940-PRELOAD-2-NEXT: s_load_dword s5, s[0:1], 0xc +; GFX940-PRELOAD-2-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x10 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s4 +; GFX940-PRELOAD-2-NEXT: global_store_short v0, v1, s[2:3] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s5 +; GFX940-PRELOAD-2-NEXT: global_store_dword v0, v1, s[6:7] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_endpgm +; +; GFX940-PRELOAD-8-LABEL: i16_i32_kernel_preload_arg: +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-8-NEXT: ; %bb.0: +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s4 +; GFX940-PRELOAD-8-NEXT: global_store_short v0, v1, s[2:3] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s5 +; GFX940-PRELOAD-8-NEXT: global_store_dword v0, v1, s[6:7] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: s_endpgm +; +; GFX90a-NO-PRELOAD-LABEL: i16_i32_kernel_preload_arg: +; GFX90a-NO-PRELOAD: ; %bb.0: +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[6:7], s[4:5], 0x10 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s2 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v2, s3 +; GFX90a-NO-PRELOAD-NEXT: global_store_short v0, v1, s[0:1] +; GFX90a-NO-PRELOAD-NEXT: global_store_dword v0, v2, s[6:7] +; GFX90a-NO-PRELOAD-NEXT: s_endpgm +; +; GFX90a-PRELOAD-2-LABEL: i16_i32_kernel_preload_arg: +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-2-NEXT: ; %bb.0: +; GFX90a-PRELOAD-2-NEXT: s_load_dword s2, s[4:5], 0xc +; GFX90a-PRELOAD-2-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x10 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s8 +; GFX90a-PRELOAD-2-NEXT: global_store_short v0, v1, s[6:7] +; GFX90a-PRELOAD-2-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s2 +; GFX90a-PRELOAD-2-NEXT: global_store_dword v0, v1, s[0:1] +; GFX90a-PRELOAD-2-NEXT: s_endpgm +; +; GFX90a-PRELOAD-8-LABEL: i16_i32_kernel_preload_arg: +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-8-NEXT: ; %bb.0: +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s8 +; GFX90a-PRELOAD-8-NEXT: global_store_short v0, v1, s[6:7] +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s9 +; GFX90a-PRELOAD-8-NEXT: global_store_dword v0, v1, s[10:11] +; GFX90a-PRELOAD-8-NEXT: s_endpgm + store i16 %in, ptr addrspace(1) %out + store i32 %in2, ptr addrspace(1) %out2 + ret void +} + +define amdgpu_kernel void @i16_v3i32_kernel_preload_arg(ptr addrspace(1) %out, i16 %in, <3 x i32> %in2, ptr addrspace(1) %out2) { +; GFX940-NO-PRELOAD-LABEL: i16_v3i32_kernel_preload_arg: +; GFX940-NO-PRELOAD: ; %bb.0: +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x10 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX940-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NO-PRELOAD-NEXT: s_load_dword s7, s[0:1], 0x8 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[8:9], s[0:1], 0x20 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v3, 0 +; GFX940-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v4, s7 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, s4 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s5 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v2, s6 +; GFX940-NO-PRELOAD-NEXT: global_store_short v3, v4, s[2:3] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: global_store_dwordx3 v3, v[0:2], s[8:9] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: s_endpgm +; +; GFX940-PRELOAD-2-LABEL: i16_v3i32_kernel_preload_arg: +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-2-NEXT: ; %bb.0: +; GFX940-PRELOAD-2-NEXT: s_load_dwordx4 s[8:11], s[0:1], 0x10 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v3, 0 +; GFX940-PRELOAD-2-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x20 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v4, s4 +; GFX940-PRELOAD-2-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s8 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s9 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v2, s10 +; GFX940-PRELOAD-2-NEXT: global_store_short v3, v4, s[2:3] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: global_store_dwordx3 v3, v[0:2], s[0:1] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_endpgm +; +; GFX940-PRELOAD-8-LABEL: i16_v3i32_kernel_preload_arg: +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-8-NEXT: ; %bb.0: +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v3, 0 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v4, s4 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s6 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s7 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v2, s8 +; GFX940-PRELOAD-8-NEXT: global_store_short v3, v4, s[2:3] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: global_store_dwordx3 v3, v[0:2], s[10:11] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: s_endpgm +; +; GFX90a-NO-PRELOAD-LABEL: i16_v3i32_kernel_preload_arg: +; GFX90a-NO-PRELOAD: ; %bb.0: +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x10 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[6:7], s[4:5], 0x0 +; GFX90a-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-NO-PRELOAD-NEXT: s_load_dword s3, s[4:5], 0x8 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[8:9], s[4:5], 0x20 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v3, 0 +; GFX90a-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v4, s3 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, s0 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s1 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v2, s2 +; GFX90a-NO-PRELOAD-NEXT: global_store_short v3, v4, s[6:7] +; GFX90a-NO-PRELOAD-NEXT: global_store_dwordx3 v3, v[0:2], s[8:9] +; GFX90a-NO-PRELOAD-NEXT: s_endpgm +; +; GFX90a-PRELOAD-2-LABEL: i16_v3i32_kernel_preload_arg: +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-2-NEXT: ; %bb.0: +; GFX90a-PRELOAD-2-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x10 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v3, 0 +; GFX90a-PRELOAD-2-NEXT: s_load_dwordx2 s[4:5], s[4:5], 0x20 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v4, s8 +; GFX90a-PRELOAD-2-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s0 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s1 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v2, s2 +; GFX90a-PRELOAD-2-NEXT: global_store_short v3, v4, s[6:7] +; GFX90a-PRELOAD-2-NEXT: global_store_dwordx3 v3, v[0:2], s[4:5] +; GFX90a-PRELOAD-2-NEXT: s_endpgm +; +; GFX90a-PRELOAD-8-LABEL: i16_v3i32_kernel_preload_arg: +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-8-NEXT: ; %bb.0: +; GFX90a-PRELOAD-8-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x20 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v3, 0 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v4, s8 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s10 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s11 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v2, s12 +; GFX90a-PRELOAD-8-NEXT: global_store_short v3, v4, s[6:7] +; GFX90a-PRELOAD-8-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-PRELOAD-8-NEXT: global_store_dwordx3 v3, v[0:2], s[0:1] +; GFX90a-PRELOAD-8-NEXT: s_endpgm + store i16 %in, ptr addrspace(1) %out + store <3 x i32> %in2, ptr addrspace(1) %out2 + ret void +} + +define amdgpu_kernel void @i16_i16_kernel_preload_arg(ptr addrspace(1) %out, i16 %in, i16 %in2, ptr addrspace(1) %out2) { +; GFX940-NO-PRELOAD-LABEL: i16_i16_kernel_preload_arg: +; GFX940-NO-PRELOAD: ; %bb.0: +; GFX940-NO-PRELOAD-NEXT: s_load_dword s6, s[0:1], 0x8 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x10 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s6 +; GFX940-NO-PRELOAD-NEXT: global_store_short v0, v1, s[2:3] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: global_store_short_d16_hi v0, v1, s[4:5] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: s_endpgm +; +; GFX940-PRELOAD-2-LABEL: i16_i16_kernel_preload_arg: +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-2-NEXT: ; %bb.0: +; GFX940-PRELOAD-2-NEXT: s_load_dword s5, s[0:1], 0x8 +; GFX940-PRELOAD-2-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x10 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s4 +; GFX940-PRELOAD-2-NEXT: global_store_short v0, v1, s[2:3] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s5 +; GFX940-PRELOAD-2-NEXT: global_store_short_d16_hi v0, v1, s[6:7] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_endpgm +; +; GFX940-PRELOAD-8-LABEL: i16_i16_kernel_preload_arg: +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-8-NEXT: ; %bb.0: +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s4 +; GFX940-PRELOAD-8-NEXT: global_store_short v0, v1, s[2:3] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: global_store_short_d16_hi v0, v1, s[6:7] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: s_endpgm +; +; GFX90a-NO-PRELOAD-LABEL: i16_i16_kernel_preload_arg: +; GFX90a-NO-PRELOAD: ; %bb.0: +; GFX90a-NO-PRELOAD-NEXT: s_load_dword s6, s[4:5], 0x8 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[4:5], 0x10 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s6 +; GFX90a-NO-PRELOAD-NEXT: global_store_short v0, v1, s[0:1] +; GFX90a-NO-PRELOAD-NEXT: global_store_short_d16_hi v0, v1, s[2:3] +; GFX90a-NO-PRELOAD-NEXT: s_endpgm +; +; GFX90a-PRELOAD-2-LABEL: i16_i16_kernel_preload_arg: +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-2-NEXT: ; %bb.0: +; GFX90a-PRELOAD-2-NEXT: s_load_dword s2, s[4:5], 0x8 +; GFX90a-PRELOAD-2-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x10 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s8 +; GFX90a-PRELOAD-2-NEXT: global_store_short v0, v1, s[6:7] +; GFX90a-PRELOAD-2-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s2 +; GFX90a-PRELOAD-2-NEXT: global_store_short_d16_hi v0, v1, s[0:1] +; GFX90a-PRELOAD-2-NEXT: s_endpgm +; +; GFX90a-PRELOAD-8-LABEL: i16_i16_kernel_preload_arg: +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-8-NEXT: ; %bb.0: +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s8 +; GFX90a-PRELOAD-8-NEXT: global_store_short v0, v1, s[6:7] +; GFX90a-PRELOAD-8-NEXT: global_store_short_d16_hi v0, v1, s[10:11] +; GFX90a-PRELOAD-8-NEXT: s_endpgm + store i16 %in, ptr addrspace(1) %out + store i16 %in2, ptr addrspace(1) %out2 + ret void +} + +define amdgpu_kernel void @i16_v2i8_kernel_preload_arg(ptr addrspace(1) %out, i16 %in, <2 x i8> %in2, ptr addrspace(1) %out2) { +; GFX940-NO-PRELOAD-LABEL: i16_v2i8_kernel_preload_arg: +; GFX940-NO-PRELOAD: ; %bb.0: +; GFX940-NO-PRELOAD-NEXT: s_load_dword s6, s[0:1], 0x8 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX940-NO-PRELOAD-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x10 +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s6 +; GFX940-NO-PRELOAD-NEXT: global_store_short v0, v1, s[2:3] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: global_store_short_d16_hi v0, v1, s[4:5] sc0 sc1 +; GFX940-NO-PRELOAD-NEXT: s_endpgm +; +; GFX940-PRELOAD-2-LABEL: i16_v2i8_kernel_preload_arg: +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-2-NEXT: ; %bb.0: +; GFX940-PRELOAD-2-NEXT: s_load_dword s5, s[0:1], 0x8 +; GFX940-PRELOAD-2-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x10 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s4 +; GFX940-PRELOAD-2-NEXT: global_store_short v0, v1, s[2:3] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s5 +; GFX940-PRELOAD-2-NEXT: global_store_short_d16_hi v0, v1, s[6:7] sc0 sc1 +; GFX940-PRELOAD-2-NEXT: s_endpgm +; +; GFX940-PRELOAD-8-LABEL: i16_v2i8_kernel_preload_arg: +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-8-NEXT: ; %bb.0: +; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s4, 24 +; GFX940-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v0, 8, s0 +; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s4, 16 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, 0 +; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v2, s4 +; GFX940-PRELOAD-8-NEXT: v_or_b32_sdwa v0, s0, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX940-PRELOAD-8-NEXT: global_store_short v1, v2, s[2:3] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: global_store_short v1, v0, s[6:7] sc0 sc1 +; GFX940-PRELOAD-8-NEXT: s_endpgm +; +; GFX90a-NO-PRELOAD-LABEL: i16_v2i8_kernel_preload_arg: +; GFX90a-NO-PRELOAD: ; %bb.0: +; GFX90a-NO-PRELOAD-NEXT: s_load_dword s6, s[4:5], 0x8 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x0 +; GFX90a-NO-PRELOAD-NEXT: s_load_dwordx2 s[2:3], s[4:5], 0x10 +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-NO-PRELOAD-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-NO-PRELOAD-NEXT: v_mov_b32_e32 v1, s6 +; GFX90a-NO-PRELOAD-NEXT: global_store_short v0, v1, s[0:1] +; GFX90a-NO-PRELOAD-NEXT: global_store_short_d16_hi v0, v1, s[2:3] +; GFX90a-NO-PRELOAD-NEXT: s_endpgm +; +; GFX90a-PRELOAD-2-LABEL: i16_v2i8_kernel_preload_arg: +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-2-NEXT: ; %bb.0: +; GFX90a-PRELOAD-2-NEXT: s_load_dword s2, s[4:5], 0x8 +; GFX90a-PRELOAD-2-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x10 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s8 +; GFX90a-PRELOAD-2-NEXT: global_store_short v0, v1, s[6:7] +; GFX90a-PRELOAD-2-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s2 +; GFX90a-PRELOAD-2-NEXT: global_store_short_d16_hi v0, v1, s[0:1] +; GFX90a-PRELOAD-2-NEXT: s_endpgm +; +; GFX90a-PRELOAD-8-LABEL: i16_v2i8_kernel_preload_arg: +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-8-NEXT: ; %bb.0: +; GFX90a-PRELOAD-8-NEXT: s_lshr_b32 s0, s8, 24 +; GFX90a-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v0, 8, s0 +; GFX90a-PRELOAD-8-NEXT: s_lshr_b32 s0, s8, 16 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, 0 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v2, s8 +; GFX90a-PRELOAD-8-NEXT: v_or_b32_sdwa v0, s0, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX90a-PRELOAD-8-NEXT: global_store_short v1, v2, s[6:7] +; GFX90a-PRELOAD-8-NEXT: global_store_short v1, v0, s[10:11] +; GFX90a-PRELOAD-8-NEXT: s_endpgm + store i16 %in, ptr addrspace(1) %out + store <2 x i8> %in2, ptr addrspace(1) %out2 + ret void +} -- GitLab From 8de7890572296830b27b6e6db39b36810bc98c31 Mon Sep 17 00:00:00 2001 From: Mingming Liu Date: Sun, 19 May 2024 22:22:47 -0700 Subject: [PATCH 051/793] [ThinLTO] Populate declaration import status except for distributed ThinLTO under a default-off new option (#88024) The goal is to populate `declaration` import status if a new flag`-import-declaration` is on. * For in-process ThinLTO, the `declaration` status is visible to backend `function-import` pass, so `FunctionImporter::importFunctions` should read the import status and be no-op for declaration summaries. Basically, the postlink pipeline is updated to keep its current behavior (import definitions), but not updated to handle `declaration` summaries. Two use cases (better call-graph sort and cross-module auto-init) would use this bit differently. * For distributed ThinLTO, the `declaration` status is not serialized to bitcode. As discussed, https://github.com/llvm/llvm-project/pull/87600 will do this. [1] https://discourse.llvm.org/t/rfc-for-better-call-graph-sort-build-a-more-complete-call-graph-by-adding-more-indirect-call-edges/74029#support-cross-module-function-declaration-import-5 [2] https://github.com/llvm/llvm-project/pull/87597#discussion_r1556067195 --- llvm/include/llvm/IR/ModuleSummaryIndex.h | 7 + .../llvm/Transforms/IPO/FunctionImport.h | 15 +- llvm/lib/LTO/LTO.cpp | 32 ++- llvm/lib/LTO/LTOBackend.cpp | 9 +- llvm/lib/Transforms/IPO/FunctionImport.cpp | 270 ++++++++++++++---- llvm/test/ThinLTO/X86/funcimport-stats.ll | 4 +- .../ThinLTO/X86/import_callee_declaration.ll | 180 ++++++++++++ .../Transforms/FunctionImport/funcimport.ll | 5 +- llvm/tools/llvm-link/llvm-link.cpp | 6 +- 9 files changed, 443 insertions(+), 85 deletions(-) create mode 100644 llvm/test/ThinLTO/X86/import_callee_declaration.ll diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h index 5d137d4b3553..a6bb261af752 100644 --- a/llvm/include/llvm/IR/ModuleSummaryIndex.h +++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h @@ -587,6 +587,10 @@ public: void setImportKind(ImportKind IK) { Flags.ImportType = IK; } + GlobalValueSummary::ImportKind importType() const { + return static_cast(Flags.ImportType); + } + GlobalValue::VisibilityTypes getVisibility() const { return (GlobalValue::VisibilityTypes)Flags.Visibility; } @@ -1272,6 +1276,9 @@ using ModulePathStringTableTy = StringMap; /// a particular module, and provide efficient access to their summary. using GVSummaryMapTy = DenseMap; +/// A set of global value summary pointers. +using GVSummaryPtrSet = SmallPtrSet; + /// Map of a type GUID to type id string and summary (multimap used /// in case of GUID conflicts). using TypeIdSummaryMapTy = diff --git a/llvm/include/llvm/Transforms/IPO/FunctionImport.h b/llvm/include/llvm/Transforms/IPO/FunctionImport.h index c4d19e8641ec..024bba8105b8 100644 --- a/llvm/include/llvm/Transforms/IPO/FunctionImport.h +++ b/llvm/include/llvm/Transforms/IPO/FunctionImport.h @@ -31,9 +31,9 @@ class Module; /// based on the provided summary informations. class FunctionImporter { public: - /// Set of functions to import from a source module. Each entry is a set - /// containing all the GUIDs of all functions to import for a source module. - using FunctionsToImportTy = std::unordered_set; + /// The functions to import from a source module and their import type. + using FunctionsToImportTy = + DenseMap; /// The different reasons selectCallee will chose not to import a /// candidate. @@ -99,8 +99,13 @@ public: /// index's module path string table). using ImportMapTy = DenseMap; - /// The set contains an entry for every global value the module exports. - using ExportSetTy = DenseSet; + /// The map contains an entry for every global value the module exports. + /// The key is ValueInfo, and the value indicates whether the definition + /// or declaration is visible to another module. If a function's definition is + /// visible to other modules, the global values this function referenced are + /// visible and shouldn't be internalized. + /// TODO: Rename to `ExportMapTy`. + using ExportSetTy = DenseMap; /// A function of this type is used to load modules referenced by the index. using ModuleLoaderTy = diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index 5c603ac6ab47..e2754d74979e 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -121,6 +121,9 @@ void llvm::computeLTOCacheKey( support::endian::write64le(Data, I); Hasher.update(Data); }; + auto AddUint8 = [&](const uint8_t I) { + Hasher.update(ArrayRef((const uint8_t *)&I, 1)); + }; AddString(Conf.CPU); // FIXME: Hash more of Options. For now all clients initialize Options from // command-line flags (which is unsupported in production), but may set @@ -156,18 +159,18 @@ void llvm::computeLTOCacheKey( auto ModHash = Index.getModuleHash(ModuleID); Hasher.update(ArrayRef((uint8_t *)&ModHash[0], sizeof(ModHash))); - std::vector ExportsGUID; + std::vector> ExportsGUID; ExportsGUID.reserve(ExportList.size()); - for (const auto &VI : ExportList) { - auto GUID = VI.getGUID(); - ExportsGUID.push_back(GUID); - } + for (const auto &[VI, ExportType] : ExportList) + ExportsGUID.push_back( + std::make_pair(VI.getGUID(), static_cast(ExportType))); // Sort the export list elements GUIDs. llvm::sort(ExportsGUID); - for (uint64_t GUID : ExportsGUID) { + for (auto [GUID, ExportType] : ExportsGUID) { // The export list can impact the internalization, be conservative here Hasher.update(ArrayRef((uint8_t *)&GUID, sizeof(GUID))); + AddUint8(ExportType); } // Include the hash for every module we import functions from. The set of @@ -199,7 +202,7 @@ void llvm::computeLTOCacheKey( [](const ImportModule &Lhs, const ImportModule &Rhs) -> bool { return Lhs.getHash() < Rhs.getHash(); }); - std::vector ImportedGUIDs; + std::vector> ImportedGUIDs; for (const ImportModule &Entry : ImportModulesVector) { auto ModHash = Entry.getHash(); Hasher.update(ArrayRef((uint8_t *)&ModHash[0], sizeof(ModHash))); @@ -207,11 +210,13 @@ void llvm::computeLTOCacheKey( AddUint64(Entry.getFunctions().size()); ImportedGUIDs.clear(); - for (auto &Fn : Entry.getFunctions()) - ImportedGUIDs.push_back(Fn); + for (auto &[Fn, ImportType] : Entry.getFunctions()) + ImportedGUIDs.push_back(std::make_pair(Fn, ImportType)); llvm::sort(ImportedGUIDs); - for (auto &GUID : ImportedGUIDs) + for (auto &[GUID, Type] : ImportedGUIDs) { AddUint64(GUID); + AddUint8(Type); + } } // Include the hash for the resolved ODR. @@ -281,9 +286,9 @@ void llvm::computeLTOCacheKey( // Imported functions may introduce new uses of type identifier resolutions, // so we need to collect their used resolutions as well. for (const ImportModule &ImpM : ImportModulesVector) - for (auto &ImpF : ImpM.getFunctions()) { + for (auto &[GUID, UnusedImportType] : ImpM.getFunctions()) { GlobalValueSummary *S = - Index.findSummaryInModule(ImpF, ImpM.getIdentifier()); + Index.findSummaryInModule(GUID, ImpM.getIdentifier()); AddUsedThings(S); // If this is an alias, we also care about any types/etc. that the aliasee // may reference. @@ -1395,6 +1400,7 @@ public: llvm::StringRef ModulePath, const std::string &NewModulePath) { std::map ModuleToSummariesForIndex; + std::error_code EC; gatherImportedSummariesForModule(ModulePath, ModuleToDefinedGVSummaries, ImportList, ModuleToSummariesForIndex); @@ -1403,6 +1409,8 @@ public: sys::fs::OpenFlags::OF_None); if (EC) return errorCodeToError(EC); + + // TODO: Serialize declaration bits to bitcode. writeIndexToFile(CombinedIndex, OS, &ModuleToSummariesForIndex); if (ShouldEmitImportsFiles) { diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp index d4b89ede2d71..58434feec6f9 100644 --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -721,7 +721,14 @@ bool lto::initImportList(const Module &M, if (Summary->modulePath() == M.getModuleIdentifier()) continue; // Add an entry to provoke importing by thinBackend. - ImportList[Summary->modulePath()].insert(GUID); + // Try emplace the entry first. If an entry with the same key already + // exists, set the value to 'std::min(existing-value, new-value)' to make + // sure a definition takes precedence over a declaration. + auto [Iter, Inserted] = ImportList[Summary->modulePath()].try_emplace( + GUID, Summary->importType()); + + if (!Inserted) + Iter->second = std::min(Iter->second, Summary->importType()); } } return true; diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp index 68f9799616ae..a116fd653534 100644 --- a/llvm/lib/Transforms/IPO/FunctionImport.cpp +++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp @@ -140,6 +140,17 @@ static cl::opt ImportAllIndex("import-all-index", cl::desc("Import all external functions in index.")); +/// This is a test-only option. +/// If this option is enabled, the ThinLTO indexing step will import each +/// function declaration as a fallback. In a real build this may increase ram +/// usage of the indexing step unnecessarily. +/// TODO: Implement selective import (based on combined summary analysis) to +/// ensure the imported function has a use case in the postlink pipeline. +static cl::opt ImportDeclaration( + "import-declaration", cl::init(false), cl::Hidden, + cl::desc("If true, import function declaration as fallback if the function " + "definition is not imported.")); + /// Pass a workload description file - an example of workload would be the /// functions executed to satisfy a RPC request. A workload is defined by a root /// function and the list of functions that are (frequently) needed to satisfy @@ -245,8 +256,12 @@ static auto qualifyCalleeCandidates( } /// Given a list of possible callee implementation for a call site, select one -/// that fits the \p Threshold. If none are found, the Reason will give the last -/// reason for the failure (last, in the order of CalleeSummaryList entries). +/// that fits the \p Threshold for function definition import. If none are +/// found, the Reason will give the last reason for the failure (last, in the +/// order of CalleeSummaryList entries). While looking for a callee definition, +/// sets \p TooLargeOrNoInlineSummary to the last seen too-large or noinline +/// candidate; other modules may want to know the function summary or +/// declaration even if a definition is not needed. /// /// FIXME: select "best" instead of first that fits. But what is "best"? /// - The smallest: more likely to be inlined. @@ -259,24 +274,32 @@ static const GlobalValueSummary * selectCallee(const ModuleSummaryIndex &Index, ArrayRef> CalleeSummaryList, unsigned Threshold, StringRef CallerModulePath, + const GlobalValueSummary *&TooLargeOrNoInlineSummary, FunctionImporter::ImportFailureReason &Reason) { + // Records the last summary with reason noinline or too-large. + TooLargeOrNoInlineSummary = nullptr; auto QualifiedCandidates = qualifyCalleeCandidates(Index, CalleeSummaryList, CallerModulePath); for (auto QualifiedValue : QualifiedCandidates) { Reason = QualifiedValue.first; + // Skip a summary if its import is not (proved to be) legal. if (Reason != FunctionImporter::ImportFailureReason::None) continue; auto *Summary = cast(QualifiedValue.second->getBaseObject()); + // Don't bother importing the definition if the chance of inlining it is + // not high enough (except under `--force-import-all`). if ((Summary->instCount() > Threshold) && !Summary->fflags().AlwaysInline && !ForceImportAll) { + TooLargeOrNoInlineSummary = Summary; Reason = FunctionImporter::ImportFailureReason::TooLarge; continue; } - // Don't bother importing if we can't inline it anyway. + // Don't bother importing the definition if we can't inline it anyway. if (Summary->fflags().NoInline && !ForceImportAll) { + TooLargeOrNoInlineSummary = Summary; Reason = FunctionImporter::ImportFailureReason::NoInline; continue; } @@ -358,17 +381,27 @@ class GlobalsImporter final { if (!GVS || !Index.canImportGlobalVar(GVS, /* AnalyzeRefs */ true) || LocalNotInModule(GVS)) continue; - auto ILI = ImportList[RefSummary->modulePath()].insert(VI.getGUID()); + + // If there isn't an entry for GUID, insert pair. + // Otherwise, definition should take precedence over declaration. + auto [Iter, Inserted] = + ImportList[RefSummary->modulePath()].try_emplace( + VI.getGUID(), GlobalValueSummary::Definition); // Only update stat and exports if we haven't already imported this // variable. - if (!ILI.second) + if (!Inserted) { + // Set the value to 'std::min(existing-value, new-value)' to make + // sure a definition takes precedence over a declaration. + Iter->second = std::min(GlobalValueSummary::Definition, Iter->second); break; + } NumImportedGlobalVarsThinLink++; // Any references made by this variable will be marked exported // later, in ComputeCrossModuleImport, after import decisions are // complete, which is more efficient than adding them here. if (ExportLists) - (*ExportLists)[RefSummary->modulePath()].insert(VI); + (*ExportLists)[RefSummary->modulePath()][VI] = + GlobalValueSummary::Definition; // If variable is not writeonly we attempt to recursively analyze // its references in order to import referenced constants. @@ -545,10 +578,11 @@ class WorkloadImportsManager : public ModuleImportsManager { LLVM_DEBUG(dbgs() << "[Workload][Including]" << VI.name() << " from " << ExportingModule << " : " << Function::getGUID(VI.name()) << "\n"); - ImportList[ExportingModule].insert(VI.getGUID()); + ImportList[ExportingModule][VI.getGUID()] = + GlobalValueSummary::Definition; GVI.onImportingSummary(*GVS); if (ExportLists) - (*ExportLists)[ExportingModule].insert(VI); + (*ExportLists)[ExportingModule][VI] = GlobalValueSummary::Definition; } LLVM_DEBUG(dbgs() << "[Workload] Done\n"); } @@ -769,9 +803,28 @@ static void computeImportForFunction( } FunctionImporter::ImportFailureReason Reason{}; - CalleeSummary = selectCallee(Index, VI.getSummaryList(), NewThreshold, - Summary.modulePath(), Reason); + + // `SummaryForDeclImport` is an summary eligible for declaration import. + const GlobalValueSummary *SummaryForDeclImport = nullptr; + CalleeSummary = + selectCallee(Index, VI.getSummaryList(), NewThreshold, + Summary.modulePath(), SummaryForDeclImport, Reason); if (!CalleeSummary) { + // There isn't a callee for definition import but one for declaration + // import. + if (ImportDeclaration && SummaryForDeclImport) { + StringRef DeclSourceModule = SummaryForDeclImport->modulePath(); + + // Since definition takes precedence over declaration for the same VI, + // try emplace pair without checking insert result. + // If insert doesn't happen, there must be an existing entry keyed by + // VI. + if (ExportLists) + (*ExportLists)[DeclSourceModule].try_emplace( + VI, GlobalValueSummary::Declaration); + ImportList[DeclSourceModule].try_emplace( + VI.getGUID(), GlobalValueSummary::Declaration); + } // Update with new larger threshold if this was a retry (otherwise // we would have already inserted with NewThreshold above). Also // update failure info if requested. @@ -816,11 +869,15 @@ static void computeImportForFunction( "selectCallee() didn't honor the threshold"); auto ExportModulePath = ResolvedCalleeSummary->modulePath(); - auto ILI = ImportList[ExportModulePath].insert(VI.getGUID()); + + // Try emplace the definition entry, and update stats based on insertion + // status. + auto [Iter, Inserted] = ImportList[ExportModulePath].try_emplace( + VI.getGUID(), GlobalValueSummary::Definition); + // We previously decided to import this GUID definition if it was already // inserted in the set of imports from the exporting module. - bool PreviouslyImported = !ILI.second; - if (!PreviouslyImported) { + if (Inserted || Iter->second == GlobalValueSummary::Declaration) { NumImportedFunctionsThinLink++; if (IsHotCallsite) NumImportedHotFunctionsThinLink++; @@ -828,11 +885,14 @@ static void computeImportForFunction( NumImportedCriticalFunctionsThinLink++; } + if (Iter->second == GlobalValueSummary::Declaration) + Iter->second = GlobalValueSummary::Definition; + // Any calls/references made by this function will be marked exported // later, in ComputeCrossModuleImport, after import decisions are // complete, which is more efficient than adding them here. if (ExportLists) - (*ExportLists)[ExportModulePath].insert(VI); + (*ExportLists)[ExportModulePath][VI] = GlobalValueSummary::Definition; } auto GetAdjustedThreshold = [](unsigned Threshold, bool IsHotCallsite) { @@ -939,12 +999,20 @@ static bool isGlobalVarSummary(const ModuleSummaryIndex &Index, } template -static unsigned numGlobalVarSummaries(const ModuleSummaryIndex &Index, - T &Cont) { +static unsigned numGlobalVarSummaries(const ModuleSummaryIndex &Index, T &Cont, + unsigned &DefinedGVS, + unsigned &DefinedFS) { unsigned NumGVS = 0; - for (auto &V : Cont) - if (isGlobalVarSummary(Index, V)) + DefinedGVS = 0; + DefinedFS = 0; + for (auto &[GUID, Type] : Cont) { + if (isGlobalVarSummary(Index, GUID)) { + if (Type == GlobalValueSummary::Definition) + ++DefinedGVS; ++NumGVS; + } else if (Type == GlobalValueSummary::Definition) + ++DefinedFS; + } return NumGVS; } #endif @@ -954,13 +1022,12 @@ static bool checkVariableImport( const ModuleSummaryIndex &Index, DenseMap &ImportLists, DenseMap &ExportLists) { - DenseSet FlattenedImports; for (auto &ImportPerModule : ImportLists) for (auto &ExportPerModule : ImportPerModule.second) - FlattenedImports.insert(ExportPerModule.second.begin(), - ExportPerModule.second.end()); + for (auto &[GUID, Type] : ExportPerModule.second) + FlattenedImports.insert(GUID); // Checks that all GUIDs of read/writeonly vars we see in export lists // are also in the import lists. Otherwise we my face linker undefs, @@ -979,7 +1046,7 @@ static bool checkVariableImport( }; for (auto &ExportPerModule : ExportLists) - for (auto &VI : ExportPerModule.second) + for (auto &[VI, Unused] : ExportPerModule.second) if (!FlattenedImports.count(VI.getGUID()) && IsReadOrWriteOnlyVarNeedingImporting(ExportPerModule.first, VI)) return false; @@ -1015,7 +1082,11 @@ void llvm::ComputeCrossModuleImport( FunctionImporter::ExportSetTy NewExports; const auto &DefinedGVSummaries = ModuleToDefinedGVSummaries.lookup(ELI.first); - for (auto &EI : ELI.second) { + for (auto &[EI, Type] : ELI.second) { + // If a variable is exported as a declaration, its 'refs' and 'calls' are + // not further exported. + if (Type == GlobalValueSummary::Declaration) + continue; // Find the copy defined in the exporting module so that we can mark the // values it references in that specific definition as exported. // Below we will add all references and called values, without regard to @@ -1034,22 +1105,31 @@ void llvm::ComputeCrossModuleImport( // we convert such variables initializers to "zeroinitializer". // See processGlobalForThinLTO. if (!Index.isWriteOnly(GVS)) - for (const auto &VI : GVS->refs()) - NewExports.insert(VI); + for (const auto &VI : GVS->refs()) { + // Try to emplace the declaration entry. If a definition entry + // already exists for key `VI`, this is a no-op. + NewExports.try_emplace(VI, GlobalValueSummary::Declaration); + } } else { auto *FS = cast(S); - for (const auto &Edge : FS->calls()) - NewExports.insert(Edge.first); - for (const auto &Ref : FS->refs()) - NewExports.insert(Ref); + for (const auto &Edge : FS->calls()) { + // Try to emplace the declaration entry. If a definition entry + // already exists for key `VI`, this is a no-op. + NewExports.try_emplace(Edge.first, GlobalValueSummary::Declaration); + } + for (const auto &Ref : FS->refs()) { + // Try to emplace the declaration entry. If a definition entry + // already exists for key `VI`, this is a no-op. + NewExports.try_emplace(Ref, GlobalValueSummary::Declaration); + } } } - // Prune list computed above to only include values defined in the exporting - // module. We do this after the above insertion since we may hit the same - // ref/call target multiple times in above loop, and it is more efficient to - // avoid a set lookup each time. + // Prune list computed above to only include values defined in the + // exporting module. We do this after the above insertion since we may hit + // the same ref/call target multiple times in above loop, and it is more + // efficient to avoid a set lookup each time. for (auto EI = NewExports.begin(); EI != NewExports.end();) { - if (!DefinedGVSummaries.count(EI->getGUID())) + if (!DefinedGVSummaries.count(EI->first.getGUID())) NewExports.erase(EI++); else ++EI; @@ -1064,18 +1144,29 @@ void llvm::ComputeCrossModuleImport( for (auto &ModuleImports : ImportLists) { auto ModName = ModuleImports.first; auto &Exports = ExportLists[ModName]; - unsigned NumGVS = numGlobalVarSummaries(Index, Exports); - LLVM_DEBUG(dbgs() << "* Module " << ModName << " exports " - << Exports.size() - NumGVS << " functions and " << NumGVS - << " vars. Imports from " << ModuleImports.second.size() - << " modules.\n"); + unsigned DefinedGVS = 0, DefinedFS = 0; + unsigned NumGVS = + numGlobalVarSummaries(Index, Exports, DefinedGVS, DefinedFS); + LLVM_DEBUG(dbgs() << "* Module " << ModName << " exports " << DefinedFS + << " function as definitions, " + << Exports.size() - NumGVS - DefinedFS + << " functions as declarations, " << DefinedGVS + << " var definitions and " << NumGVS - DefinedGVS + << " var declarations. Imports from " + << ModuleImports.second.size() << " modules.\n"); for (auto &Src : ModuleImports.second) { auto SrcModName = Src.first; - unsigned NumGVSPerMod = numGlobalVarSummaries(Index, Src.second); - LLVM_DEBUG(dbgs() << " - " << Src.second.size() - NumGVSPerMod - << " functions imported from " << SrcModName << "\n"); - LLVM_DEBUG(dbgs() << " - " << NumGVSPerMod - << " global vars imported from " << SrcModName << "\n"); + unsigned DefinedGVS = 0, DefinedFS = 0; + unsigned NumGVSPerMod = + numGlobalVarSummaries(Index, Src.second, DefinedGVS, DefinedFS); + LLVM_DEBUG(dbgs() << " - " << DefinedFS << " function definitions and " + << Src.second.size() - NumGVSPerMod - DefinedFS + << " function declarations imported from " << SrcModName + << "\n"); + LLVM_DEBUG(dbgs() << " - " << DefinedGVS << " global vars definition and " + << NumGVSPerMod - DefinedGVS + << " global vars declaration imported from " + << SrcModName << "\n"); } } #endif @@ -1089,11 +1180,17 @@ static void dumpImportListForModule(const ModuleSummaryIndex &Index, << ImportList.size() << " modules.\n"); for (auto &Src : ImportList) { auto SrcModName = Src.first; - unsigned NumGVSPerMod = numGlobalVarSummaries(Index, Src.second); - LLVM_DEBUG(dbgs() << " - " << Src.second.size() - NumGVSPerMod - << " functions imported from " << SrcModName << "\n"); - LLVM_DEBUG(dbgs() << " - " << NumGVSPerMod << " vars imported from " - << SrcModName << "\n"); + unsigned DefinedGVS = 0, DefinedFS = 0; + unsigned NumGVSPerMod = + numGlobalVarSummaries(Index, Src.second, DefinedGVS, DefinedFS); + LLVM_DEBUG(dbgs() << " - " << DefinedFS << " function definitions and " + << Src.second.size() - DefinedFS - NumGVSPerMod + << " function declarations imported from " << SrcModName + << "\n"); + LLVM_DEBUG(dbgs() << " - " << DefinedGVS << " var definitions and " + << NumGVSPerMod - DefinedGVS + << " var declarations imported from " << SrcModName + << "\n"); } } #endif @@ -1149,7 +1246,13 @@ static void ComputeCrossModuleImportForModuleFromIndexForTest( if (Summary->modulePath() == ModulePath) continue; // Add an entry to provoke importing by thinBackend. - ImportList[Summary->modulePath()].insert(GUID); + auto [Iter, Inserted] = ImportList[Summary->modulePath()].try_emplace( + GUID, Summary->importType()); + if (!Inserted) { + // Use 'std::min' to make sure definition (with enum value 0) takes + // precedence over declaration (with enum value 1). + Iter->second = std::min(Iter->second, Summary->importType()); + } } #ifndef NDEBUG dumpImportListForModule(Index, ModulePath, ImportList); @@ -1339,13 +1442,17 @@ void llvm::gatherImportedSummariesForModule( // Include summaries for imports. for (const auto &ILI : ImportList) { auto &SummariesForIndex = ModuleToSummariesForIndex[std::string(ILI.first)]; + const auto &DefinedGVSummaries = ModuleToDefinedGVSummaries.lookup(ILI.first); - for (const auto &GI : ILI.second) { - const auto &DS = DefinedGVSummaries.find(GI); + for (const auto &[GUID, Type] : ILI.second) { + const auto &DS = DefinedGVSummaries.find(GUID); assert(DS != DefinedGVSummaries.end() && "Expected a defined summary for imported global value"); - SummariesForIndex[GI] = DS->second; + if (Type == GlobalValueSummary::Declaration) + continue; + + SummariesForIndex[GUID] = DS->second; } } } @@ -1617,6 +1724,16 @@ Expected FunctionImporter::importFunctions( for (const auto &FunctionsToImportPerModule : ImportList) { ModuleNameOrderedList.insert(FunctionsToImportPerModule.first); } + + auto getImportType = [&](const FunctionsToImportTy &GUIDToImportType, + GlobalValue::GUID GUID) + -> std::optional { + auto Iter = GUIDToImportType.find(GUID); + if (Iter == GUIDToImportType.end()) + return std::nullopt; + return Iter->second; + }; + for (const auto &Name : ModuleNameOrderedList) { // Get the module for the import const auto &FunctionsToImportPerModule = ImportList.find(Name); @@ -1634,17 +1751,27 @@ Expected FunctionImporter::importFunctions( return std::move(Err); auto &ImportGUIDs = FunctionsToImportPerModule->second; + // Find the globals to import SetVector GlobalsToImport; for (Function &F : *SrcModule) { if (!F.hasName()) continue; auto GUID = F.getGUID(); - auto Import = ImportGUIDs.count(GUID); - LLVM_DEBUG(dbgs() << (Import ? "Is" : "Not") << " importing function " + auto MaybeImportType = getImportType(ImportGUIDs, GUID); + + bool ImportDefinition = + (MaybeImportType && + (*MaybeImportType == GlobalValueSummary::Definition)); + + LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not") + << " importing function" + << (ImportDefinition + ? " definition " + : (MaybeImportType ? " declaration " : " ")) << GUID << " " << F.getName() << " from " << SrcModule->getSourceFileName() << "\n"); - if (Import) { + if (ImportDefinition) { if (Error Err = F.materialize()) return std::move(Err); // MemProf should match function's definition and summary, @@ -1670,11 +1797,20 @@ Expected FunctionImporter::importFunctions( if (!GV.hasName()) continue; auto GUID = GV.getGUID(); - auto Import = ImportGUIDs.count(GUID); - LLVM_DEBUG(dbgs() << (Import ? "Is" : "Not") << " importing global " + auto MaybeImportType = getImportType(ImportGUIDs, GUID); + + bool ImportDefinition = + (MaybeImportType && + (*MaybeImportType == GlobalValueSummary::Definition)); + + LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not") + << " importing global" + << (ImportDefinition + ? " definition " + : (MaybeImportType ? " declaration " : " ")) << GUID << " " << GV.getName() << " from " << SrcModule->getSourceFileName() << "\n"); - if (Import) { + if (ImportDefinition) { if (Error Err = GV.materialize()) return std::move(Err); ImportedGVCount += GlobalsToImport.insert(&GV); @@ -1684,11 +1820,20 @@ Expected FunctionImporter::importFunctions( if (!GA.hasName() || isa(GA.getAliaseeObject())) continue; auto GUID = GA.getGUID(); - auto Import = ImportGUIDs.count(GUID); - LLVM_DEBUG(dbgs() << (Import ? "Is" : "Not") << " importing alias " + auto MaybeImportType = getImportType(ImportGUIDs, GUID); + + bool ImportDefinition = + (MaybeImportType && + (*MaybeImportType == GlobalValueSummary::Definition)); + + LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not") + << " importing alias" + << (ImportDefinition + ? " definition " + : (MaybeImportType ? " declaration " : " ")) << GUID << " " << GA.getName() << " from " << SrcModule->getSourceFileName() << "\n"); - if (Import) { + if (ImportDefinition) { if (Error Err = GA.materialize()) return std::move(Err); // Import alias as a copy of its aliasee. @@ -1754,6 +1899,7 @@ Expected FunctionImporter::importFunctions( NumImportedFunctions += (ImportedCount - ImportedGVCount); NumImportedGlobalVars += ImportedGVCount; + // TODO: Print counters for definitions and declarations in the debugging log. LLVM_DEBUG(dbgs() << "Imported " << ImportedCount - ImportedGVCount << " functions for Module " << DestModule.getModuleIdentifier() << "\n"); diff --git a/llvm/test/ThinLTO/X86/funcimport-stats.ll b/llvm/test/ThinLTO/X86/funcimport-stats.ll index 913b13004c1c..7fcd33855fe1 100644 --- a/llvm/test/ThinLTO/X86/funcimport-stats.ll +++ b/llvm/test/ThinLTO/X86/funcimport-stats.ll @@ -9,8 +9,8 @@ ; RUN: cat %t4 | grep 'Is importing aliasee' | count 1 ; RUN: cat %t4 | FileCheck %s -; CHECK: - [[NUM_FUNCS:[0-9]+]] functions imported from -; CHECK-NEXT: - [[NUM_VARS:[0-9]+]] global vars imported from +; CHECK: - [[NUM_FUNCS:[0-9]+]] function definitions and 0 function declarations imported from +; CHECK-NEXT: - [[NUM_VARS:[0-9]+]] global vars definition and 0 global vars declaration imported from ; CHECK: [[NUM_FUNCS]] function-import - Number of functions imported in backend ; CHECK-NEXT: [[NUM_FUNCS]] function-import - Number of functions thin link decided to import diff --git a/llvm/test/ThinLTO/X86/import_callee_declaration.ll b/llvm/test/ThinLTO/X86/import_callee_declaration.ll new file mode 100644 index 000000000000..df8a9ce6f710 --- /dev/null +++ b/llvm/test/ThinLTO/X86/import_callee_declaration.ll @@ -0,0 +1,180 @@ +; "-debug-only" requires asserts. +; REQUIRES: asserts +; RUN: rm -rf %t && split-file %s %t && cd %t + +; Generate per-module summaries. +; RUN: opt -module-summary main.ll -o main.bc +; RUN: opt -module-summary lib.ll -o lib.bc + +; Generate the combined summary and distributed indices. + +; - For function import, set 'import-instr-limit' to 7 and fall back to import +; function declarations. +; - In main.ll, function 'main' calls 'small_func' and 'large_func'. Both callees +; are defined in lib.ll. 'small_func' has two indirect callees, one is smaller +; and the other one is larger. Both callees of 'small_func' are defined in lib.ll. +; - Given the import limit, in main's combined summary, the import type of 'small_func' +; and 'small_indirect_callee' will be 'definition', and the import type of +; 'large_func' and 'large_indirect_callee' will be 'declaration'. +; +; The test will disassemble combined summaries and check the import type is +; correct. Right now postlink optimizer pipeline doesn't do anything (e.g., +; import the declaration or de-serialize summary attributes yet) so there is +; nothing to test more than the summary content. +; +; RUN: llvm-lto2 run \ +; RUN: -debug-only=function-import \ +; RUN: -import-instr-limit=7 \ +; RUN: -import-declaration \ +; RUN: -thinlto-distributed-indexes \ +; RUN: -r=main.bc,main,px \ +; RUN: -r=main.bc,small_func, \ +; RUN: -r=main.bc,large_func, \ +; RUN: -r=lib.bc,callee,pl \ +; RUN: -r=lib.bc,large_indirect_callee,px \ +; RUN: -r=lib.bc,small_func,px \ +; RUN: -r=lib.bc,large_func,px \ +; RUN: -r=lib.bc,large_indirect_callee_alias,px \ +; RUN: -r=lib.bc,calleeAddrs,px -o summary main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=DUMP +; +; RUN: llvm-lto -thinlto-action=thinlink -import-declaration -import-instr-limit=7 -o combined.index.bc main.bc lib.bc +; RUN: llvm-lto -thinlto-action=distributedindexes -debug-only=function-import -import-declaration -import-instr-limit=7 -thinlto-index combined.index.bc main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=DUMP + +; DUMP: - 2 function definitions and 3 function declarations imported from lib.bc + +; First disassemble per-module summary and find out the GUID for {large_func, large_indirect_callee}. +; +; RUN: llvm-dis lib.bc -o - | FileCheck %s --check-prefix=LIB-DIS +; LIB-DIS: [[LARGEFUNC:\^[0-9]+]] = gv: (name: "large_func", summaries: {{.*}}) ; guid = 2418497564662708935 +; LIB-DIS: [[LARGEINDIRECT:\^[0-9]+]] = gv: (name: "large_indirect_callee", summaries: {{.*}}) ; guid = 14343440786664691134 +; LIB-DIS: [[LARGEINDIRECTALIAS:\^[0-9]+]] = gv: (name: "large_indirect_callee_alias", summaries: {{.*}}, aliasee: [[LARGEINDIRECT]] +; +; Secondly disassemble main's combined summary and test that large callees are +; not imported as declarations yet. +; +; RUN: llvm-dis main.bc.thinlto.bc -o - | FileCheck %s --check-prefix=MAIN-DIS +; +; MAIN-DIS: [[LIBMOD:\^[0-9]+]] = module: (path: "lib.bc", hash: (0, 0, 0, 0, 0)) +; MAIN-DIS-NOT: [[LARGEFUNC:\^[0-9]+]] = gv: (guid: 2418497564662708935, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}}))) +; MAIN-DIS-NOT: [[LARGEINDIRECT:\^[0-9]+]] = gv: (guid: 14343440786664691134, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}}))) +; MAIN-DIS-NOT: [[LARGEINDIRECTALIAS:\^[0-9]+]] = gv: (guid: 16730173943625350469, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration) + +; Run in-process ThinLTO and tests that +; 1. `callee` remains internalized even if the symbols of its callers +; (large_func and large_indirect_callee) are exported as declarations and visible to main module. +; 2. the debugging logs from `function-import` pass are expected. + +; RUN: llvm-lto2 run \ +; RUN: -debug-only=function-import \ +; RUN: -save-temps \ +; RUN: -import-instr-limit=7 \ +; RUN: -import-declaration \ +; RUN: -r=main.bc,main,px \ +; RUN: -r=main.bc,small_func, \ +; RUN: -r=main.bc,large_func, \ +; RUN: -r=lib.bc,callee,pl \ +; RUN: -r=lib.bc,large_indirect_callee,px \ +; RUN: -r=lib.bc,small_func,px \ +; RUN: -r=lib.bc,large_func,px \ +; RUN: -r=lib.bc,large_indirect_callee_alias,px \ +; RUN: -r=lib.bc,calleeAddrs,px -o in-process main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=IMPORTDUMP + +; Test import status from debugging logs. +; TODO: Serialize declaration bit and test declaration bits are correctly set, +; and extend this test case to test IR once postlink optimizer makes use of +; the import type for declarations. +; IMPORTDUMP-DAG: Not importing function 11825436545918268459 callee from lib.cc +; IMPORTDUMP-DAG: Is importing function declaration 14343440786664691134 large_indirect_callee from lib.cc +; IMPORTDUMP-DAG: Is importing function definition 13568239288960714650 small_indirect_callee from lib.cc +; IMPORTDUMP-DAG: Is importing function definition 6976996067367342685 small_func from lib.cc +; IMPORTDUMP-DAG: Is importing function declaration 2418497564662708935 large_func from lib.cc +; IMPORTDUMP-DAG: Not importing global 7680325410415171624 calleeAddrs from lib.cc +; IMPORTDUMP-DAG: Is importing alias declaration 16730173943625350469 large_indirect_callee_alias from lib.cc + +; RUN: llvm-dis in-process.1.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT + +; RUN: llvm-dis in-process.2.2.internalize.bc -o - | FileCheck %s --check-prefix=INTERNALIZE + +; IMPORT-DAG: define available_externally void @small_func +; IMPORT-DAG: define available_externally hidden void @small_indirect_callee +; IMPORT-DAG: declare void @large_func +; IMPORT-NOT: large_indirect_callee +; IMPORT-NOT: large_indirect_callee_alias + +; INTERNALIZE: define internal void @callee() + +;--- main.ll +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @main() { + call void @small_func() + call void @large_func() + ret i32 0 +} + +declare void @small_func() + +; large_func without attributes +declare void @large_func() + +;--- lib.ll +source_filename = "lib.cc" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@calleeAddrs = global [3 x ptr] [ptr @large_indirect_callee, ptr @small_indirect_callee, ptr @large_indirect_callee_alias] + +define void @callee() #1 { + ret void +} + +define void @large_indirect_callee()#2 { + call void @callee() + call void @callee() + call void @callee() + call void @callee() + call void @callee() + call void @callee() + call void @callee() + ret void +} + +define internal void @small_indirect_callee() #0 { + ret void +} + +@large_indirect_callee_alias = alias void(), ptr @large_indirect_callee + +define void @small_func() { +entry: + %0 = load ptr, ptr @calleeAddrs + call void %0(), !prof !0 + %1 = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @calleeAddrs, i64 0, i64 1) + call void %1(), !prof !1 + %2 = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @calleeAddrs, i64 0, i64 2) + call void %2(), !prof !2 + ret void +} + +define void @large_func() #0 { +entry: + call void @callee() + call void @callee() + call void @callee() + call void @callee() + call void @callee() + call void @callee() + call void @callee() + ret void +} + +attributes #0 = { nounwind norecurse } + +attributes #1 = { noinline } + +attributes #2 = { norecurse } + +!0 = !{!"VP", i32 0, i64 1, i64 14343440786664691134, i64 1} +!1 = !{!"VP", i32 0, i64 1, i64 13568239288960714650, i64 1} +!2 = !{!"VP", i32 0, i64 1, i64 16730173943625350469, i64 1} diff --git a/llvm/test/Transforms/FunctionImport/funcimport.ll b/llvm/test/Transforms/FunctionImport/funcimport.ll index a0968a67f5ce..635750b33fff 100644 --- a/llvm/test/Transforms/FunctionImport/funcimport.ll +++ b/llvm/test/Transforms/FunctionImport/funcimport.ll @@ -166,7 +166,8 @@ declare void @variadic_va_start(...) ; GUID-DAG: GUID {{.*}} is linkoncefunc ; DUMP: Module [[M1:.*]] imports from 1 module -; DUMP-NEXT: 15 functions imported from [[M2:.*]] -; DUMP-NEXT: 4 vars imported from [[M2]] +; DUMP-NEXT: 15 function definitions and 0 function declarations imported from [[M2:.*]] +; DUMP-NEXT: 4 var definitions and 0 var declarations imported from [[M2]] + ; DUMP: Imported 15 functions for Module [[M1]] ; DUMP-NEXT: Imported 4 global variables for Module [[M1]] diff --git a/llvm/tools/llvm-link/llvm-link.cpp b/llvm/tools/llvm-link/llvm-link.cpp index 7794f2d81ed0..1b90fce76fbd 100644 --- a/llvm/tools/llvm-link/llvm-link.cpp +++ b/llvm/tools/llvm-link/llvm-link.cpp @@ -377,9 +377,13 @@ static bool importFunctions(const char *argv0, Module &DestModule) { if (Verbose) errs() << "Importing " << FunctionName << " from " << FileName << "\n"; + // `-import` specifies the `` pairs to import as + // definition, so make the import type definition directly. + // FIXME: A follow-up patch should add test coverage for import declaration + // in `llvm-link` CLI (e.g., by introducing a new command line option). auto &Entry = ImportList[FileNameStringCache.insert(FileName).first->getKey()]; - Entry.insert(F->getGUID()); + Entry[F->getGUID()] = GlobalValueSummary::Definition; } auto CachedModuleLoader = [&](StringRef Identifier) { return ModuleLoaderCache.takeModule(std::string(Identifier)); -- GitLab From d316a0bd48ceb4a0ee851d729291a2cdcc8818eb Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Mon, 20 May 2024 13:35:52 +0800 Subject: [PATCH 052/793] [NFC] Remove unused ASTWriter::getTypeID As the title suggests, the `ASTWriter:getTypeID` method is not used. This patch removes it. --- clang/include/clang/Serialization/ASTWriter.h | 3 -- clang/lib/Serialization/ASTCommon.h | 24 ------------ clang/lib/Serialization/ASTWriter.cpp | 38 ++++++++++++------- 3 files changed, 25 insertions(+), 40 deletions(-) diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 6aa2796a41e0..88192e439a3f 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -715,9 +715,6 @@ public: /// Force a type to be emitted and get its ID. serialization::TypeID GetOrCreateTypeID(QualType T); - /// Determine the type ID of an already-emitted type. - serialization::TypeID getTypeID(QualType T) const; - /// Find the first local declaration of a given local redeclarable /// decl. const Decl *getFirstLocalDecl(const Decl *D); diff --git a/clang/lib/Serialization/ASTCommon.h b/clang/lib/Serialization/ASTCommon.h index 296642e3674a..0230908d3e05 100644 --- a/clang/lib/Serialization/ASTCommon.h +++ b/clang/lib/Serialization/ASTCommon.h @@ -46,30 +46,6 @@ enum DeclUpdateKind { TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT); -template -TypeID MakeTypeID(ASTContext &Context, QualType T, IdxForTypeTy IdxForType) { - if (T.isNull()) - return PREDEF_TYPE_NULL_ID; - - unsigned FastQuals = T.getLocalFastQualifiers(); - T.removeLocalFastQualifiers(); - - if (T.hasLocalNonFastQualifiers()) - return IdxForType(T).asTypeID(FastQuals); - - assert(!T.hasLocalQualifiers()); - - if (const BuiltinType *BT = dyn_cast(T.getTypePtr())) - return TypeIdxFromBuiltin(BT).asTypeID(FastQuals); - - if (T == Context.AutoDeductTy) - return TypeIdx(PREDEF_TYPE_AUTO_DEDUCT).asTypeID(FastQuals); - if (T == Context.AutoRRefDeductTy) - return TypeIdx(PREDEF_TYPE_AUTO_RREF_DEDUCT).asTypeID(FastQuals); - - return IdxForType(T).asTypeID(FastQuals); -} - unsigned ComputeHash(Selector Sel); /// Retrieve the "definitive" declaration that provides all of the diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 2a107e4c56a3..1d6d96932ba2 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -6074,6 +6074,31 @@ void ASTWriter::AddTypeRef(QualType T, RecordDataImpl &Record) { Record.push_back(GetOrCreateTypeID(T)); } +template +static TypeID MakeTypeID(ASTContext &Context, QualType T, + IdxForTypeTy IdxForType) { + if (T.isNull()) + return PREDEF_TYPE_NULL_ID; + + unsigned FastQuals = T.getLocalFastQualifiers(); + T.removeLocalFastQualifiers(); + + if (T.hasLocalNonFastQualifiers()) + return IdxForType(T).asTypeID(FastQuals); + + assert(!T.hasLocalQualifiers()); + + if (const BuiltinType *BT = dyn_cast(T.getTypePtr())) + return TypeIdxFromBuiltin(BT).asTypeID(FastQuals); + + if (T == Context.AutoDeductTy) + return TypeIdx(PREDEF_TYPE_AUTO_DEDUCT).asTypeID(FastQuals); + if (T == Context.AutoRRefDeductTy) + return TypeIdx(PREDEF_TYPE_AUTO_RREF_DEDUCT).asTypeID(FastQuals); + + return IdxForType(T).asTypeID(FastQuals); +} + TypeID ASTWriter::GetOrCreateTypeID(QualType T) { assert(Context); return MakeTypeID(*Context, T, [&](QualType T) -> TypeIdx { @@ -6097,19 +6122,6 @@ TypeID ASTWriter::GetOrCreateTypeID(QualType T) { }); } -TypeID ASTWriter::getTypeID(QualType T) const { - assert(Context); - return MakeTypeID(*Context, T, [&](QualType T) -> TypeIdx { - if (T.isNull()) - return TypeIdx(); - assert(!T.getLocalFastQualifiers()); - - TypeIdxMap::const_iterator I = TypeIdxs.find(T); - assert(I != TypeIdxs.end() && "Type not emitted!"); - return I->second; - }); -} - void ASTWriter::AddEmittedDeclRef(const Decl *D, RecordDataImpl &Record) { if (!wasDeclEmitted(D)) return; -- GitLab From b6e102e08cd35543175459494211a3a15f793302 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 20 May 2024 07:40:54 +0200 Subject: [PATCH 053/793] [SCEV] Don't use non-deterministic constant folding for trip counts (#90942) When calculating the exit count exhaustively, if any of the involved operations is non-deterministic, the exit count we compute at compile-time and the exit count at run-time may differ. Using these non-deterministic constant folding results is only correct if we actually replace all uses of the instruction with the value. SCEV (or its consumers) generally don't do this. Handle this by adding a new AllowNonDeterministic flag to the constant folding API, and disabling it in SCEV. If non-deterministic results are not allowed, do not fold FP lib calls in general, and FP operations returning NaNs in particular. This could be made more precise (some FP libcalls like fabs are fully deterministic), but I don't think this that precise handling here is worthwhile. Fixes the interesting part of https://github.com/llvm/llvm-project/issues/89885. --- llvm/include/llvm/Analysis/ConstantFolding.h | 15 +- llvm/lib/Analysis/ConstantFolding.cpp | 51 ++++-- llvm/lib/Analysis/ScalarEvolution.cpp | 6 +- .../ScalarEvolution/exhaustive-trip-counts.ll | 152 ++++++++++++++++++ 4 files changed, 208 insertions(+), 16 deletions(-) diff --git a/llvm/include/llvm/Analysis/ConstantFolding.h b/llvm/include/llvm/Analysis/ConstantFolding.h index c54b1e8f01d2..58b38fb8b036 100644 --- a/llvm/include/llvm/Analysis/ConstantFolding.h +++ b/llvm/include/llvm/Analysis/ConstantFolding.h @@ -68,9 +68,16 @@ Constant *ConstantFoldConstant(const Constant *C, const DataLayout &DL, /// fold instructions like loads and stores, which have no constant expression /// form. /// +/// In some cases, constant folding may return one value chosen from a set of +/// multiple legal return values. For example, the exact bit pattern of NaN +/// results is not guaranteed. Using such a result is usually only valid if +/// all uses of the original operation are replaced by the constant-folded +/// result. The \p AllowNonDeterministic parameter controls whether this is +/// allowed. Constant *ConstantFoldInstOperands(Instruction *I, ArrayRef Ops, const DataLayout &DL, - const TargetLibraryInfo *TLI = nullptr); + const TargetLibraryInfo *TLI = nullptr, + bool AllowNonDeterministic = true); /// Attempt to constant fold a compare instruction (icmp/fcmp) with the /// specified operands. Returns null or a constant expression of the specified @@ -95,7 +102,8 @@ Constant *ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS, /// Returns null or a constant expression of the specified operands on failure. Constant *ConstantFoldFPInstOperands(unsigned Opcode, Constant *LHS, Constant *RHS, const DataLayout &DL, - const Instruction *I); + const Instruction *I, + bool AllowNonDeterministic = true); /// Attempt to flush float point constant according to denormal mode set in the /// instruction's parent function attributes. If so, return a zero with the @@ -190,7 +198,8 @@ bool canConstantFoldCallTo(const CallBase *Call, const Function *F); /// with the specified arguments, returning null if unsuccessful. Constant *ConstantFoldCall(const CallBase *Call, Function *F, ArrayRef Operands, - const TargetLibraryInfo *TLI = nullptr); + const TargetLibraryInfo *TLI = nullptr, + bool AllowNonDeterministic = true); Constant *ConstantFoldBinaryIntrinsic(Intrinsic::ID ID, Constant *LHS, Constant *RHS, Type *Ty, diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 046a76945380..524e84f3f3de 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -992,7 +992,8 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, unsigned Opcode, ArrayRef Ops, const DataLayout &DL, - const TargetLibraryInfo *TLI) { + const TargetLibraryInfo *TLI, + bool AllowNonDeterministic) { Type *DestTy = InstOrCE->getType(); if (Instruction::isUnaryOp(Opcode)) @@ -1011,7 +1012,8 @@ Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, unsigned Opcode, // TODO: If a constant expression is being folded rather than an // instruction, denormals will not be flushed/treated as zero if (const auto *I = dyn_cast(InstOrCE)) { - return ConstantFoldFPInstOperands(Opcode, Ops[0], Ops[1], DL, I); + return ConstantFoldFPInstOperands(Opcode, Ops[0], Ops[1], DL, I, + AllowNonDeterministic); } } return ConstantFoldBinaryOpOperands(Opcode, Ops[0], Ops[1], DL); @@ -1053,7 +1055,8 @@ Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, unsigned Opcode, if (auto *F = dyn_cast(Ops.back())) { const auto *Call = cast(InstOrCE); if (canConstantFoldCallTo(Call, F)) - return ConstantFoldCall(Call, F, Ops.slice(0, Ops.size() - 1), TLI); + return ConstantFoldCall(Call, F, Ops.slice(0, Ops.size() - 1), TLI, + AllowNonDeterministic); } return nullptr; case Instruction::Select: @@ -1114,8 +1117,8 @@ ConstantFoldConstantImpl(const Constant *C, const DataLayout &DL, } if (auto *CE = dyn_cast(C)) { - if (Constant *Res = - ConstantFoldInstOperandsImpl(CE, CE->getOpcode(), Ops, DL, TLI)) + if (Constant *Res = ConstantFoldInstOperandsImpl( + CE, CE->getOpcode(), Ops, DL, TLI, /*AllowNonDeterministic=*/true)) return Res; return const_cast(C); } @@ -1183,8 +1186,10 @@ Constant *llvm::ConstantFoldConstant(const Constant *C, const DataLayout &DL, Constant *llvm::ConstantFoldInstOperands(Instruction *I, ArrayRef Ops, const DataLayout &DL, - const TargetLibraryInfo *TLI) { - return ConstantFoldInstOperandsImpl(I, I->getOpcode(), Ops, DL, TLI); + const TargetLibraryInfo *TLI, + bool AllowNonDeterministic) { + return ConstantFoldInstOperandsImpl(I, I->getOpcode(), Ops, DL, TLI, + AllowNonDeterministic); } Constant *llvm::ConstantFoldCompareInstOperands( @@ -1357,7 +1362,8 @@ Constant *llvm::FlushFPConstant(Constant *Operand, const Instruction *I, Constant *llvm::ConstantFoldFPInstOperands(unsigned Opcode, Constant *LHS, Constant *RHS, const DataLayout &DL, - const Instruction *I) { + const Instruction *I, + bool AllowNonDeterministic) { if (Instruction::isBinaryOp(Opcode)) { // Flush denormal inputs if needed. Constant *Op0 = FlushFPConstant(LHS, I, /* IsOutput */ false); @@ -1367,13 +1373,30 @@ Constant *llvm::ConstantFoldFPInstOperands(unsigned Opcode, Constant *LHS, if (!Op1) return nullptr; + // If nsz or an algebraic FMF flag is set, the result of the FP operation + // may change due to future optimization. Don't constant fold them if + // non-deterministic results are not allowed. + if (!AllowNonDeterministic) + if (auto *FP = dyn_cast_or_null(I)) + if (FP->hasNoSignedZeros() || FP->hasAllowReassoc() || + FP->hasAllowContract() || FP->hasAllowReciprocal()) + return nullptr; + // Calculate constant result. Constant *C = ConstantFoldBinaryOpOperands(Opcode, Op0, Op1, DL); if (!C) return nullptr; // Flush denormal output if needed. - return FlushFPConstant(C, I, /* IsOutput */ true); + C = FlushFPConstant(C, I, /* IsOutput */ true); + if (!C) + return nullptr; + + // The precise NaN value is non-deterministic. + if (!AllowNonDeterministic && C->isNaN()) + return nullptr; + + return C; } // If instruction lacks a parent/function and the denormal mode cannot be // determined, use the default (IEEE). @@ -3401,7 +3424,8 @@ Constant *llvm::ConstantFoldBinaryIntrinsic(Intrinsic::ID ID, Constant *LHS, Constant *llvm::ConstantFoldCall(const CallBase *Call, Function *F, ArrayRef Operands, - const TargetLibraryInfo *TLI) { + const TargetLibraryInfo *TLI, + bool AllowNonDeterministic) { if (Call->isNoBuiltin()) return nullptr; if (!F->hasName()) @@ -3417,8 +3441,13 @@ Constant *llvm::ConstantFoldCall(const CallBase *Call, Function *F, return nullptr; } - StringRef Name = F->getName(); + // Conservatively assume that floating-point libcalls may be + // non-deterministic. Type *Ty = F->getReturnType(); + if (!AllowNonDeterministic && Ty->isFPOrFPVectorTy()) + return nullptr; + + StringRef Name = F->getName(); if (auto *FVTy = dyn_cast(Ty)) return ConstantFoldFixedVectorCall( Name, IID, FVTy, Operands, F->getParent()->getDataLayout(), TLI, Call); diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 254d79183a1e..704f92669a11 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -9540,7 +9540,8 @@ static Constant *EvaluateExpression(Value *V, const Loop *L, Operands[i] = C; } - return ConstantFoldInstOperands(I, Operands, DL, TLI); + return ConstantFoldInstOperands(I, Operands, DL, TLI, + /*AllowNonDeterministic=*/false); } @@ -10031,7 +10032,8 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) { Constant *C = nullptr; const DataLayout &DL = getDataLayout(); - C = ConstantFoldInstOperands(I, Operands, DL, &TLI); + C = ConstantFoldInstOperands(I, Operands, DL, &TLI, + /*AllowNonDeterministic=*/false); if (!C) return V; return getSCEV(C); diff --git a/llvm/test/Analysis/ScalarEvolution/exhaustive-trip-counts.ll b/llvm/test/Analysis/ScalarEvolution/exhaustive-trip-counts.ll index 21237f426693..cc08fa5fc7d8 100644 --- a/llvm/test/Analysis/ScalarEvolution/exhaustive-trip-counts.ll +++ b/llvm/test/Analysis/ScalarEvolution/exhaustive-trip-counts.ll @@ -27,4 +27,156 @@ for.cond.cleanup: ret void } +; Do not compute exhaustive trip count based on FP libcalls, as their exact +; return value may not be specified. +define i64 @test_fp_libcall() { +; CHECK-LABEL: 'test_fp_libcall' +; CHECK-NEXT: Determining loop execution counts for: @test_fp_libcall +; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count. +; CHECK-NEXT: Loop %loop: Unpredictable constant max backedge-taken count. +; CHECK-NEXT: Loop %loop: Unpredictable symbolic max backedge-taken count. +; +entry: + br label %loop + +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %fv = phi double [ 1.000000e+00, %entry ], [ %fv.next, %loop ] + call void @use(double %fv) + %fv.next = call double @llvm.sin.f64(double %fv) + %iv.next = add i64 %iv, 1 + %fcmp = fcmp une double %fv, 0x3FC6BA15EE8460B0 + br i1 %fcmp, label %loop, label %exit + +exit: + ret i64 %iv +} + +; Do not compute exhaustive trip count based on FP constant folding resulting +; in NaN values, as we don't specify which NaN exactly is returned. +define i64 @test_nan_sign() { +; CHECK-LABEL: 'test_nan_sign' +; CHECK-NEXT: Determining loop execution counts for: @test_nan_sign +; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count. +; CHECK-NEXT: Loop %loop: Unpredictable constant max backedge-taken count. +; CHECK-NEXT: Loop %loop: Unpredictable symbolic max backedge-taken count. +; +entry: + br label %loop + +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %fv = phi double [ -1.000000e+00, %entry ], [ %fv.next, %loop ] + call void @use(double %fv) + %a = fsub double %fv, 0x7F86C16C16C16C16 + %b = fadd double %a, %a + %fv.next = fsub double %b, %a + %iv.next = add i64 %iv, 1 + %fv.bc = bitcast double %fv to i64 + %icmp = icmp slt i64 %fv.bc, 0 + br i1 %icmp, label %loop, label %exit + +exit: + ret i64 %iv +} + +; Do not compute exhaustive trip count based on FP constant folding if the +; involved operation has nsz or one of the algebraic FMF flags (reassoc, arcp, +; contract) set. The examples in the following are dummies and don't illustrate +; real cases where FMF transforms could cause issues. + +define i64 @test_fp_nsz() { +; CHECK-LABEL: 'test_fp_nsz' +; CHECK-NEXT: Determining loop execution counts for: @test_fp_nsz +; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count. +; CHECK-NEXT: Loop %loop: Unpredictable constant max backedge-taken count. +; CHECK-NEXT: Loop %loop: Unpredictable symbolic max backedge-taken count. +; +entry: + br label %loop + +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %fv = phi double [ 1.000000e+00, %entry ], [ %fv.next, %loop ] + call void @use(double %fv) + %fv.next = fadd nsz double %fv, 1.0 + %iv.next = add i64 %iv, 1 + %fcmp = fcmp une double %fv, 100.0 + br i1 %fcmp, label %loop, label %exit + +exit: + ret i64 %iv +} + +define i64 @test_fp_reassoc() { +; CHECK-LABEL: 'test_fp_reassoc' +; CHECK-NEXT: Determining loop execution counts for: @test_fp_reassoc +; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count. +; CHECK-NEXT: Loop %loop: Unpredictable constant max backedge-taken count. +; CHECK-NEXT: Loop %loop: Unpredictable symbolic max backedge-taken count. +; +entry: + br label %loop + +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %fv = phi double [ 1.000000e+00, %entry ], [ %fv.next, %loop ] + call void @use(double %fv) + %fv.next = fadd reassoc double %fv, 1.0 + %iv.next = add i64 %iv, 1 + %fcmp = fcmp une double %fv, 100.0 + br i1 %fcmp, label %loop, label %exit + +exit: + ret i64 %iv +} + +define i64 @test_fp_arcp() { +; CHECK-LABEL: 'test_fp_arcp' +; CHECK-NEXT: Determining loop execution counts for: @test_fp_arcp +; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count. +; CHECK-NEXT: Loop %loop: Unpredictable constant max backedge-taken count. +; CHECK-NEXT: Loop %loop: Unpredictable symbolic max backedge-taken count. +; +entry: + br label %loop + +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %fv = phi double [ 1.000000e+00, %entry ], [ %fv.next, %loop ] + call void @use(double %fv) + %fv.next = fadd arcp double %fv, 1.0 + %iv.next = add i64 %iv, 1 + %fcmp = fcmp une double %fv, 100.0 + br i1 %fcmp, label %loop, label %exit + +exit: + ret i64 %iv +} + +define i64 @test_fp_contract() { +; CHECK-LABEL: 'test_fp_contract' +; CHECK-NEXT: Determining loop execution counts for: @test_fp_contract +; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count. +; CHECK-NEXT: Loop %loop: Unpredictable constant max backedge-taken count. +; CHECK-NEXT: Loop %loop: Unpredictable symbolic max backedge-taken count. +; +entry: + br label %loop + +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %fv = phi double [ 1.000000e+00, %entry ], [ %fv.next, %loop ] + call void @use(double %fv) + %fv.next = fadd contract double %fv, 1.0 + %iv.next = add i64 %iv, 1 + %fcmp = fcmp une double %fv, 100.0 + br i1 %fcmp, label %loop, label %exit + +exit: + ret i64 %iv +} + declare void @dummy() +declare void @use(double %i) +declare double @llvm.sin.f64(double) -- GitLab From 6b0733e3a35350679ea9c6056ecd28652d99017f Mon Sep 17 00:00:00 2001 From: Mingming Liu Date: Sun, 19 May 2024 22:42:18 -0700 Subject: [PATCH 054/793] Revert "[ThinLTO] Populate declaration import status except for distributed ThinLTO under a default-off new option" (#92715) Reverts llvm/llvm-project#88024 Build bot failures (https://lab.llvm.org/buildbot/#/builders/259/builds/4727 and https://lab.llvm.org/buildbot/#/builders/9/builds/43876) --- llvm/include/llvm/IR/ModuleSummaryIndex.h | 7 - .../llvm/Transforms/IPO/FunctionImport.h | 15 +- llvm/lib/LTO/LTO.cpp | 32 +-- llvm/lib/LTO/LTOBackend.cpp | 9 +- llvm/lib/Transforms/IPO/FunctionImport.cpp | 270 ++++-------------- llvm/test/ThinLTO/X86/funcimport-stats.ll | 4 +- .../ThinLTO/X86/import_callee_declaration.ll | 180 ------------ .../Transforms/FunctionImport/funcimport.ll | 5 +- llvm/tools/llvm-link/llvm-link.cpp | 6 +- 9 files changed, 85 insertions(+), 443 deletions(-) delete mode 100644 llvm/test/ThinLTO/X86/import_callee_declaration.ll diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h index a6bb261af752..5d137d4b3553 100644 --- a/llvm/include/llvm/IR/ModuleSummaryIndex.h +++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h @@ -587,10 +587,6 @@ public: void setImportKind(ImportKind IK) { Flags.ImportType = IK; } - GlobalValueSummary::ImportKind importType() const { - return static_cast(Flags.ImportType); - } - GlobalValue::VisibilityTypes getVisibility() const { return (GlobalValue::VisibilityTypes)Flags.Visibility; } @@ -1276,9 +1272,6 @@ using ModulePathStringTableTy = StringMap; /// a particular module, and provide efficient access to their summary. using GVSummaryMapTy = DenseMap; -/// A set of global value summary pointers. -using GVSummaryPtrSet = SmallPtrSet; - /// Map of a type GUID to type id string and summary (multimap used /// in case of GUID conflicts). using TypeIdSummaryMapTy = diff --git a/llvm/include/llvm/Transforms/IPO/FunctionImport.h b/llvm/include/llvm/Transforms/IPO/FunctionImport.h index 024bba8105b8..c4d19e8641ec 100644 --- a/llvm/include/llvm/Transforms/IPO/FunctionImport.h +++ b/llvm/include/llvm/Transforms/IPO/FunctionImport.h @@ -31,9 +31,9 @@ class Module; /// based on the provided summary informations. class FunctionImporter { public: - /// The functions to import from a source module and their import type. - using FunctionsToImportTy = - DenseMap; + /// Set of functions to import from a source module. Each entry is a set + /// containing all the GUIDs of all functions to import for a source module. + using FunctionsToImportTy = std::unordered_set; /// The different reasons selectCallee will chose not to import a /// candidate. @@ -99,13 +99,8 @@ public: /// index's module path string table). using ImportMapTy = DenseMap; - /// The map contains an entry for every global value the module exports. - /// The key is ValueInfo, and the value indicates whether the definition - /// or declaration is visible to another module. If a function's definition is - /// visible to other modules, the global values this function referenced are - /// visible and shouldn't be internalized. - /// TODO: Rename to `ExportMapTy`. - using ExportSetTy = DenseMap; + /// The set contains an entry for every global value the module exports. + using ExportSetTy = DenseSet; /// A function of this type is used to load modules referenced by the index. using ModuleLoaderTy = diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index e2754d74979e..5c603ac6ab47 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -121,9 +121,6 @@ void llvm::computeLTOCacheKey( support::endian::write64le(Data, I); Hasher.update(Data); }; - auto AddUint8 = [&](const uint8_t I) { - Hasher.update(ArrayRef((const uint8_t *)&I, 1)); - }; AddString(Conf.CPU); // FIXME: Hash more of Options. For now all clients initialize Options from // command-line flags (which is unsupported in production), but may set @@ -159,18 +156,18 @@ void llvm::computeLTOCacheKey( auto ModHash = Index.getModuleHash(ModuleID); Hasher.update(ArrayRef((uint8_t *)&ModHash[0], sizeof(ModHash))); - std::vector> ExportsGUID; + std::vector ExportsGUID; ExportsGUID.reserve(ExportList.size()); - for (const auto &[VI, ExportType] : ExportList) - ExportsGUID.push_back( - std::make_pair(VI.getGUID(), static_cast(ExportType))); + for (const auto &VI : ExportList) { + auto GUID = VI.getGUID(); + ExportsGUID.push_back(GUID); + } // Sort the export list elements GUIDs. llvm::sort(ExportsGUID); - for (auto [GUID, ExportType] : ExportsGUID) { + for (uint64_t GUID : ExportsGUID) { // The export list can impact the internalization, be conservative here Hasher.update(ArrayRef((uint8_t *)&GUID, sizeof(GUID))); - AddUint8(ExportType); } // Include the hash for every module we import functions from. The set of @@ -202,7 +199,7 @@ void llvm::computeLTOCacheKey( [](const ImportModule &Lhs, const ImportModule &Rhs) -> bool { return Lhs.getHash() < Rhs.getHash(); }); - std::vector> ImportedGUIDs; + std::vector ImportedGUIDs; for (const ImportModule &Entry : ImportModulesVector) { auto ModHash = Entry.getHash(); Hasher.update(ArrayRef((uint8_t *)&ModHash[0], sizeof(ModHash))); @@ -210,13 +207,11 @@ void llvm::computeLTOCacheKey( AddUint64(Entry.getFunctions().size()); ImportedGUIDs.clear(); - for (auto &[Fn, ImportType] : Entry.getFunctions()) - ImportedGUIDs.push_back(std::make_pair(Fn, ImportType)); + for (auto &Fn : Entry.getFunctions()) + ImportedGUIDs.push_back(Fn); llvm::sort(ImportedGUIDs); - for (auto &[GUID, Type] : ImportedGUIDs) { + for (auto &GUID : ImportedGUIDs) AddUint64(GUID); - AddUint8(Type); - } } // Include the hash for the resolved ODR. @@ -286,9 +281,9 @@ void llvm::computeLTOCacheKey( // Imported functions may introduce new uses of type identifier resolutions, // so we need to collect their used resolutions as well. for (const ImportModule &ImpM : ImportModulesVector) - for (auto &[GUID, UnusedImportType] : ImpM.getFunctions()) { + for (auto &ImpF : ImpM.getFunctions()) { GlobalValueSummary *S = - Index.findSummaryInModule(GUID, ImpM.getIdentifier()); + Index.findSummaryInModule(ImpF, ImpM.getIdentifier()); AddUsedThings(S); // If this is an alias, we also care about any types/etc. that the aliasee // may reference. @@ -1400,7 +1395,6 @@ public: llvm::StringRef ModulePath, const std::string &NewModulePath) { std::map ModuleToSummariesForIndex; - std::error_code EC; gatherImportedSummariesForModule(ModulePath, ModuleToDefinedGVSummaries, ImportList, ModuleToSummariesForIndex); @@ -1409,8 +1403,6 @@ public: sys::fs::OpenFlags::OF_None); if (EC) return errorCodeToError(EC); - - // TODO: Serialize declaration bits to bitcode. writeIndexToFile(CombinedIndex, OS, &ModuleToSummariesForIndex); if (ShouldEmitImportsFiles) { diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp index 58434feec6f9..d4b89ede2d71 100644 --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -721,14 +721,7 @@ bool lto::initImportList(const Module &M, if (Summary->modulePath() == M.getModuleIdentifier()) continue; // Add an entry to provoke importing by thinBackend. - // Try emplace the entry first. If an entry with the same key already - // exists, set the value to 'std::min(existing-value, new-value)' to make - // sure a definition takes precedence over a declaration. - auto [Iter, Inserted] = ImportList[Summary->modulePath()].try_emplace( - GUID, Summary->importType()); - - if (!Inserted) - Iter->second = std::min(Iter->second, Summary->importType()); + ImportList[Summary->modulePath()].insert(GUID); } } return true; diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp index a116fd653534..68f9799616ae 100644 --- a/llvm/lib/Transforms/IPO/FunctionImport.cpp +++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp @@ -140,17 +140,6 @@ static cl::opt ImportAllIndex("import-all-index", cl::desc("Import all external functions in index.")); -/// This is a test-only option. -/// If this option is enabled, the ThinLTO indexing step will import each -/// function declaration as a fallback. In a real build this may increase ram -/// usage of the indexing step unnecessarily. -/// TODO: Implement selective import (based on combined summary analysis) to -/// ensure the imported function has a use case in the postlink pipeline. -static cl::opt ImportDeclaration( - "import-declaration", cl::init(false), cl::Hidden, - cl::desc("If true, import function declaration as fallback if the function " - "definition is not imported.")); - /// Pass a workload description file - an example of workload would be the /// functions executed to satisfy a RPC request. A workload is defined by a root /// function and the list of functions that are (frequently) needed to satisfy @@ -256,12 +245,8 @@ static auto qualifyCalleeCandidates( } /// Given a list of possible callee implementation for a call site, select one -/// that fits the \p Threshold for function definition import. If none are -/// found, the Reason will give the last reason for the failure (last, in the -/// order of CalleeSummaryList entries). While looking for a callee definition, -/// sets \p TooLargeOrNoInlineSummary to the last seen too-large or noinline -/// candidate; other modules may want to know the function summary or -/// declaration even if a definition is not needed. +/// that fits the \p Threshold. If none are found, the Reason will give the last +/// reason for the failure (last, in the order of CalleeSummaryList entries). /// /// FIXME: select "best" instead of first that fits. But what is "best"? /// - The smallest: more likely to be inlined. @@ -274,32 +259,24 @@ static const GlobalValueSummary * selectCallee(const ModuleSummaryIndex &Index, ArrayRef> CalleeSummaryList, unsigned Threshold, StringRef CallerModulePath, - const GlobalValueSummary *&TooLargeOrNoInlineSummary, FunctionImporter::ImportFailureReason &Reason) { - // Records the last summary with reason noinline or too-large. - TooLargeOrNoInlineSummary = nullptr; auto QualifiedCandidates = qualifyCalleeCandidates(Index, CalleeSummaryList, CallerModulePath); for (auto QualifiedValue : QualifiedCandidates) { Reason = QualifiedValue.first; - // Skip a summary if its import is not (proved to be) legal. if (Reason != FunctionImporter::ImportFailureReason::None) continue; auto *Summary = cast(QualifiedValue.second->getBaseObject()); - // Don't bother importing the definition if the chance of inlining it is - // not high enough (except under `--force-import-all`). if ((Summary->instCount() > Threshold) && !Summary->fflags().AlwaysInline && !ForceImportAll) { - TooLargeOrNoInlineSummary = Summary; Reason = FunctionImporter::ImportFailureReason::TooLarge; continue; } - // Don't bother importing the definition if we can't inline it anyway. + // Don't bother importing if we can't inline it anyway. if (Summary->fflags().NoInline && !ForceImportAll) { - TooLargeOrNoInlineSummary = Summary; Reason = FunctionImporter::ImportFailureReason::NoInline; continue; } @@ -381,27 +358,17 @@ class GlobalsImporter final { if (!GVS || !Index.canImportGlobalVar(GVS, /* AnalyzeRefs */ true) || LocalNotInModule(GVS)) continue; - - // If there isn't an entry for GUID, insert pair. - // Otherwise, definition should take precedence over declaration. - auto [Iter, Inserted] = - ImportList[RefSummary->modulePath()].try_emplace( - VI.getGUID(), GlobalValueSummary::Definition); + auto ILI = ImportList[RefSummary->modulePath()].insert(VI.getGUID()); // Only update stat and exports if we haven't already imported this // variable. - if (!Inserted) { - // Set the value to 'std::min(existing-value, new-value)' to make - // sure a definition takes precedence over a declaration. - Iter->second = std::min(GlobalValueSummary::Definition, Iter->second); + if (!ILI.second) break; - } NumImportedGlobalVarsThinLink++; // Any references made by this variable will be marked exported // later, in ComputeCrossModuleImport, after import decisions are // complete, which is more efficient than adding them here. if (ExportLists) - (*ExportLists)[RefSummary->modulePath()][VI] = - GlobalValueSummary::Definition; + (*ExportLists)[RefSummary->modulePath()].insert(VI); // If variable is not writeonly we attempt to recursively analyze // its references in order to import referenced constants. @@ -578,11 +545,10 @@ class WorkloadImportsManager : public ModuleImportsManager { LLVM_DEBUG(dbgs() << "[Workload][Including]" << VI.name() << " from " << ExportingModule << " : " << Function::getGUID(VI.name()) << "\n"); - ImportList[ExportingModule][VI.getGUID()] = - GlobalValueSummary::Definition; + ImportList[ExportingModule].insert(VI.getGUID()); GVI.onImportingSummary(*GVS); if (ExportLists) - (*ExportLists)[ExportingModule][VI] = GlobalValueSummary::Definition; + (*ExportLists)[ExportingModule].insert(VI); } LLVM_DEBUG(dbgs() << "[Workload] Done\n"); } @@ -803,28 +769,9 @@ static void computeImportForFunction( } FunctionImporter::ImportFailureReason Reason{}; - - // `SummaryForDeclImport` is an summary eligible for declaration import. - const GlobalValueSummary *SummaryForDeclImport = nullptr; - CalleeSummary = - selectCallee(Index, VI.getSummaryList(), NewThreshold, - Summary.modulePath(), SummaryForDeclImport, Reason); + CalleeSummary = selectCallee(Index, VI.getSummaryList(), NewThreshold, + Summary.modulePath(), Reason); if (!CalleeSummary) { - // There isn't a callee for definition import but one for declaration - // import. - if (ImportDeclaration && SummaryForDeclImport) { - StringRef DeclSourceModule = SummaryForDeclImport->modulePath(); - - // Since definition takes precedence over declaration for the same VI, - // try emplace pair without checking insert result. - // If insert doesn't happen, there must be an existing entry keyed by - // VI. - if (ExportLists) - (*ExportLists)[DeclSourceModule].try_emplace( - VI, GlobalValueSummary::Declaration); - ImportList[DeclSourceModule].try_emplace( - VI.getGUID(), GlobalValueSummary::Declaration); - } // Update with new larger threshold if this was a retry (otherwise // we would have already inserted with NewThreshold above). Also // update failure info if requested. @@ -869,15 +816,11 @@ static void computeImportForFunction( "selectCallee() didn't honor the threshold"); auto ExportModulePath = ResolvedCalleeSummary->modulePath(); - - // Try emplace the definition entry, and update stats based on insertion - // status. - auto [Iter, Inserted] = ImportList[ExportModulePath].try_emplace( - VI.getGUID(), GlobalValueSummary::Definition); - + auto ILI = ImportList[ExportModulePath].insert(VI.getGUID()); // We previously decided to import this GUID definition if it was already // inserted in the set of imports from the exporting module. - if (Inserted || Iter->second == GlobalValueSummary::Declaration) { + bool PreviouslyImported = !ILI.second; + if (!PreviouslyImported) { NumImportedFunctionsThinLink++; if (IsHotCallsite) NumImportedHotFunctionsThinLink++; @@ -885,14 +828,11 @@ static void computeImportForFunction( NumImportedCriticalFunctionsThinLink++; } - if (Iter->second == GlobalValueSummary::Declaration) - Iter->second = GlobalValueSummary::Definition; - // Any calls/references made by this function will be marked exported // later, in ComputeCrossModuleImport, after import decisions are // complete, which is more efficient than adding them here. if (ExportLists) - (*ExportLists)[ExportModulePath][VI] = GlobalValueSummary::Definition; + (*ExportLists)[ExportModulePath].insert(VI); } auto GetAdjustedThreshold = [](unsigned Threshold, bool IsHotCallsite) { @@ -999,20 +939,12 @@ static bool isGlobalVarSummary(const ModuleSummaryIndex &Index, } template -static unsigned numGlobalVarSummaries(const ModuleSummaryIndex &Index, T &Cont, - unsigned &DefinedGVS, - unsigned &DefinedFS) { +static unsigned numGlobalVarSummaries(const ModuleSummaryIndex &Index, + T &Cont) { unsigned NumGVS = 0; - DefinedGVS = 0; - DefinedFS = 0; - for (auto &[GUID, Type] : Cont) { - if (isGlobalVarSummary(Index, GUID)) { - if (Type == GlobalValueSummary::Definition) - ++DefinedGVS; + for (auto &V : Cont) + if (isGlobalVarSummary(Index, V)) ++NumGVS; - } else if (Type == GlobalValueSummary::Definition) - ++DefinedFS; - } return NumGVS; } #endif @@ -1022,12 +954,13 @@ static bool checkVariableImport( const ModuleSummaryIndex &Index, DenseMap &ImportLists, DenseMap &ExportLists) { + DenseSet FlattenedImports; for (auto &ImportPerModule : ImportLists) for (auto &ExportPerModule : ImportPerModule.second) - for (auto &[GUID, Type] : ExportPerModule.second) - FlattenedImports.insert(GUID); + FlattenedImports.insert(ExportPerModule.second.begin(), + ExportPerModule.second.end()); // Checks that all GUIDs of read/writeonly vars we see in export lists // are also in the import lists. Otherwise we my face linker undefs, @@ -1046,7 +979,7 @@ static bool checkVariableImport( }; for (auto &ExportPerModule : ExportLists) - for (auto &[VI, Unused] : ExportPerModule.second) + for (auto &VI : ExportPerModule.second) if (!FlattenedImports.count(VI.getGUID()) && IsReadOrWriteOnlyVarNeedingImporting(ExportPerModule.first, VI)) return false; @@ -1082,11 +1015,7 @@ void llvm::ComputeCrossModuleImport( FunctionImporter::ExportSetTy NewExports; const auto &DefinedGVSummaries = ModuleToDefinedGVSummaries.lookup(ELI.first); - for (auto &[EI, Type] : ELI.second) { - // If a variable is exported as a declaration, its 'refs' and 'calls' are - // not further exported. - if (Type == GlobalValueSummary::Declaration) - continue; + for (auto &EI : ELI.second) { // Find the copy defined in the exporting module so that we can mark the // values it references in that specific definition as exported. // Below we will add all references and called values, without regard to @@ -1105,31 +1034,22 @@ void llvm::ComputeCrossModuleImport( // we convert such variables initializers to "zeroinitializer". // See processGlobalForThinLTO. if (!Index.isWriteOnly(GVS)) - for (const auto &VI : GVS->refs()) { - // Try to emplace the declaration entry. If a definition entry - // already exists for key `VI`, this is a no-op. - NewExports.try_emplace(VI, GlobalValueSummary::Declaration); - } + for (const auto &VI : GVS->refs()) + NewExports.insert(VI); } else { auto *FS = cast(S); - for (const auto &Edge : FS->calls()) { - // Try to emplace the declaration entry. If a definition entry - // already exists for key `VI`, this is a no-op. - NewExports.try_emplace(Edge.first, GlobalValueSummary::Declaration); - } - for (const auto &Ref : FS->refs()) { - // Try to emplace the declaration entry. If a definition entry - // already exists for key `VI`, this is a no-op. - NewExports.try_emplace(Ref, GlobalValueSummary::Declaration); - } + for (const auto &Edge : FS->calls()) + NewExports.insert(Edge.first); + for (const auto &Ref : FS->refs()) + NewExports.insert(Ref); } } - // Prune list computed above to only include values defined in the - // exporting module. We do this after the above insertion since we may hit - // the same ref/call target multiple times in above loop, and it is more - // efficient to avoid a set lookup each time. + // Prune list computed above to only include values defined in the exporting + // module. We do this after the above insertion since we may hit the same + // ref/call target multiple times in above loop, and it is more efficient to + // avoid a set lookup each time. for (auto EI = NewExports.begin(); EI != NewExports.end();) { - if (!DefinedGVSummaries.count(EI->first.getGUID())) + if (!DefinedGVSummaries.count(EI->getGUID())) NewExports.erase(EI++); else ++EI; @@ -1144,29 +1064,18 @@ void llvm::ComputeCrossModuleImport( for (auto &ModuleImports : ImportLists) { auto ModName = ModuleImports.first; auto &Exports = ExportLists[ModName]; - unsigned DefinedGVS = 0, DefinedFS = 0; - unsigned NumGVS = - numGlobalVarSummaries(Index, Exports, DefinedGVS, DefinedFS); - LLVM_DEBUG(dbgs() << "* Module " << ModName << " exports " << DefinedFS - << " function as definitions, " - << Exports.size() - NumGVS - DefinedFS - << " functions as declarations, " << DefinedGVS - << " var definitions and " << NumGVS - DefinedGVS - << " var declarations. Imports from " - << ModuleImports.second.size() << " modules.\n"); + unsigned NumGVS = numGlobalVarSummaries(Index, Exports); + LLVM_DEBUG(dbgs() << "* Module " << ModName << " exports " + << Exports.size() - NumGVS << " functions and " << NumGVS + << " vars. Imports from " << ModuleImports.second.size() + << " modules.\n"); for (auto &Src : ModuleImports.second) { auto SrcModName = Src.first; - unsigned DefinedGVS = 0, DefinedFS = 0; - unsigned NumGVSPerMod = - numGlobalVarSummaries(Index, Src.second, DefinedGVS, DefinedFS); - LLVM_DEBUG(dbgs() << " - " << DefinedFS << " function definitions and " - << Src.second.size() - NumGVSPerMod - DefinedFS - << " function declarations imported from " << SrcModName - << "\n"); - LLVM_DEBUG(dbgs() << " - " << DefinedGVS << " global vars definition and " - << NumGVSPerMod - DefinedGVS - << " global vars declaration imported from " - << SrcModName << "\n"); + unsigned NumGVSPerMod = numGlobalVarSummaries(Index, Src.second); + LLVM_DEBUG(dbgs() << " - " << Src.second.size() - NumGVSPerMod + << " functions imported from " << SrcModName << "\n"); + LLVM_DEBUG(dbgs() << " - " << NumGVSPerMod + << " global vars imported from " << SrcModName << "\n"); } } #endif @@ -1180,17 +1089,11 @@ static void dumpImportListForModule(const ModuleSummaryIndex &Index, << ImportList.size() << " modules.\n"); for (auto &Src : ImportList) { auto SrcModName = Src.first; - unsigned DefinedGVS = 0, DefinedFS = 0; - unsigned NumGVSPerMod = - numGlobalVarSummaries(Index, Src.second, DefinedGVS, DefinedFS); - LLVM_DEBUG(dbgs() << " - " << DefinedFS << " function definitions and " - << Src.second.size() - DefinedFS - NumGVSPerMod - << " function declarations imported from " << SrcModName - << "\n"); - LLVM_DEBUG(dbgs() << " - " << DefinedGVS << " var definitions and " - << NumGVSPerMod - DefinedGVS - << " var declarations imported from " << SrcModName - << "\n"); + unsigned NumGVSPerMod = numGlobalVarSummaries(Index, Src.second); + LLVM_DEBUG(dbgs() << " - " << Src.second.size() - NumGVSPerMod + << " functions imported from " << SrcModName << "\n"); + LLVM_DEBUG(dbgs() << " - " << NumGVSPerMod << " vars imported from " + << SrcModName << "\n"); } } #endif @@ -1246,13 +1149,7 @@ static void ComputeCrossModuleImportForModuleFromIndexForTest( if (Summary->modulePath() == ModulePath) continue; // Add an entry to provoke importing by thinBackend. - auto [Iter, Inserted] = ImportList[Summary->modulePath()].try_emplace( - GUID, Summary->importType()); - if (!Inserted) { - // Use 'std::min' to make sure definition (with enum value 0) takes - // precedence over declaration (with enum value 1). - Iter->second = std::min(Iter->second, Summary->importType()); - } + ImportList[Summary->modulePath()].insert(GUID); } #ifndef NDEBUG dumpImportListForModule(Index, ModulePath, ImportList); @@ -1442,17 +1339,13 @@ void llvm::gatherImportedSummariesForModule( // Include summaries for imports. for (const auto &ILI : ImportList) { auto &SummariesForIndex = ModuleToSummariesForIndex[std::string(ILI.first)]; - const auto &DefinedGVSummaries = ModuleToDefinedGVSummaries.lookup(ILI.first); - for (const auto &[GUID, Type] : ILI.second) { - const auto &DS = DefinedGVSummaries.find(GUID); + for (const auto &GI : ILI.second) { + const auto &DS = DefinedGVSummaries.find(GI); assert(DS != DefinedGVSummaries.end() && "Expected a defined summary for imported global value"); - if (Type == GlobalValueSummary::Declaration) - continue; - - SummariesForIndex[GUID] = DS->second; + SummariesForIndex[GI] = DS->second; } } } @@ -1724,16 +1617,6 @@ Expected FunctionImporter::importFunctions( for (const auto &FunctionsToImportPerModule : ImportList) { ModuleNameOrderedList.insert(FunctionsToImportPerModule.first); } - - auto getImportType = [&](const FunctionsToImportTy &GUIDToImportType, - GlobalValue::GUID GUID) - -> std::optional { - auto Iter = GUIDToImportType.find(GUID); - if (Iter == GUIDToImportType.end()) - return std::nullopt; - return Iter->second; - }; - for (const auto &Name : ModuleNameOrderedList) { // Get the module for the import const auto &FunctionsToImportPerModule = ImportList.find(Name); @@ -1751,27 +1634,17 @@ Expected FunctionImporter::importFunctions( return std::move(Err); auto &ImportGUIDs = FunctionsToImportPerModule->second; - // Find the globals to import SetVector GlobalsToImport; for (Function &F : *SrcModule) { if (!F.hasName()) continue; auto GUID = F.getGUID(); - auto MaybeImportType = getImportType(ImportGUIDs, GUID); - - bool ImportDefinition = - (MaybeImportType && - (*MaybeImportType == GlobalValueSummary::Definition)); - - LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not") - << " importing function" - << (ImportDefinition - ? " definition " - : (MaybeImportType ? " declaration " : " ")) + auto Import = ImportGUIDs.count(GUID); + LLVM_DEBUG(dbgs() << (Import ? "Is" : "Not") << " importing function " << GUID << " " << F.getName() << " from " << SrcModule->getSourceFileName() << "\n"); - if (ImportDefinition) { + if (Import) { if (Error Err = F.materialize()) return std::move(Err); // MemProf should match function's definition and summary, @@ -1797,20 +1670,11 @@ Expected FunctionImporter::importFunctions( if (!GV.hasName()) continue; auto GUID = GV.getGUID(); - auto MaybeImportType = getImportType(ImportGUIDs, GUID); - - bool ImportDefinition = - (MaybeImportType && - (*MaybeImportType == GlobalValueSummary::Definition)); - - LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not") - << " importing global" - << (ImportDefinition - ? " definition " - : (MaybeImportType ? " declaration " : " ")) + auto Import = ImportGUIDs.count(GUID); + LLVM_DEBUG(dbgs() << (Import ? "Is" : "Not") << " importing global " << GUID << " " << GV.getName() << " from " << SrcModule->getSourceFileName() << "\n"); - if (ImportDefinition) { + if (Import) { if (Error Err = GV.materialize()) return std::move(Err); ImportedGVCount += GlobalsToImport.insert(&GV); @@ -1820,20 +1684,11 @@ Expected FunctionImporter::importFunctions( if (!GA.hasName() || isa(GA.getAliaseeObject())) continue; auto GUID = GA.getGUID(); - auto MaybeImportType = getImportType(ImportGUIDs, GUID); - - bool ImportDefinition = - (MaybeImportType && - (*MaybeImportType == GlobalValueSummary::Definition)); - - LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not") - << " importing alias" - << (ImportDefinition - ? " definition " - : (MaybeImportType ? " declaration " : " ")) + auto Import = ImportGUIDs.count(GUID); + LLVM_DEBUG(dbgs() << (Import ? "Is" : "Not") << " importing alias " << GUID << " " << GA.getName() << " from " << SrcModule->getSourceFileName() << "\n"); - if (ImportDefinition) { + if (Import) { if (Error Err = GA.materialize()) return std::move(Err); // Import alias as a copy of its aliasee. @@ -1899,7 +1754,6 @@ Expected FunctionImporter::importFunctions( NumImportedFunctions += (ImportedCount - ImportedGVCount); NumImportedGlobalVars += ImportedGVCount; - // TODO: Print counters for definitions and declarations in the debugging log. LLVM_DEBUG(dbgs() << "Imported " << ImportedCount - ImportedGVCount << " functions for Module " << DestModule.getModuleIdentifier() << "\n"); diff --git a/llvm/test/ThinLTO/X86/funcimport-stats.ll b/llvm/test/ThinLTO/X86/funcimport-stats.ll index 7fcd33855fe1..913b13004c1c 100644 --- a/llvm/test/ThinLTO/X86/funcimport-stats.ll +++ b/llvm/test/ThinLTO/X86/funcimport-stats.ll @@ -9,8 +9,8 @@ ; RUN: cat %t4 | grep 'Is importing aliasee' | count 1 ; RUN: cat %t4 | FileCheck %s -; CHECK: - [[NUM_FUNCS:[0-9]+]] function definitions and 0 function declarations imported from -; CHECK-NEXT: - [[NUM_VARS:[0-9]+]] global vars definition and 0 global vars declaration imported from +; CHECK: - [[NUM_FUNCS:[0-9]+]] functions imported from +; CHECK-NEXT: - [[NUM_VARS:[0-9]+]] global vars imported from ; CHECK: [[NUM_FUNCS]] function-import - Number of functions imported in backend ; CHECK-NEXT: [[NUM_FUNCS]] function-import - Number of functions thin link decided to import diff --git a/llvm/test/ThinLTO/X86/import_callee_declaration.ll b/llvm/test/ThinLTO/X86/import_callee_declaration.ll deleted file mode 100644 index df8a9ce6f710..000000000000 --- a/llvm/test/ThinLTO/X86/import_callee_declaration.ll +++ /dev/null @@ -1,180 +0,0 @@ -; "-debug-only" requires asserts. -; REQUIRES: asserts -; RUN: rm -rf %t && split-file %s %t && cd %t - -; Generate per-module summaries. -; RUN: opt -module-summary main.ll -o main.bc -; RUN: opt -module-summary lib.ll -o lib.bc - -; Generate the combined summary and distributed indices. - -; - For function import, set 'import-instr-limit' to 7 and fall back to import -; function declarations. -; - In main.ll, function 'main' calls 'small_func' and 'large_func'. Both callees -; are defined in lib.ll. 'small_func' has two indirect callees, one is smaller -; and the other one is larger. Both callees of 'small_func' are defined in lib.ll. -; - Given the import limit, in main's combined summary, the import type of 'small_func' -; and 'small_indirect_callee' will be 'definition', and the import type of -; 'large_func' and 'large_indirect_callee' will be 'declaration'. -; -; The test will disassemble combined summaries and check the import type is -; correct. Right now postlink optimizer pipeline doesn't do anything (e.g., -; import the declaration or de-serialize summary attributes yet) so there is -; nothing to test more than the summary content. -; -; RUN: llvm-lto2 run \ -; RUN: -debug-only=function-import \ -; RUN: -import-instr-limit=7 \ -; RUN: -import-declaration \ -; RUN: -thinlto-distributed-indexes \ -; RUN: -r=main.bc,main,px \ -; RUN: -r=main.bc,small_func, \ -; RUN: -r=main.bc,large_func, \ -; RUN: -r=lib.bc,callee,pl \ -; RUN: -r=lib.bc,large_indirect_callee,px \ -; RUN: -r=lib.bc,small_func,px \ -; RUN: -r=lib.bc,large_func,px \ -; RUN: -r=lib.bc,large_indirect_callee_alias,px \ -; RUN: -r=lib.bc,calleeAddrs,px -o summary main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=DUMP -; -; RUN: llvm-lto -thinlto-action=thinlink -import-declaration -import-instr-limit=7 -o combined.index.bc main.bc lib.bc -; RUN: llvm-lto -thinlto-action=distributedindexes -debug-only=function-import -import-declaration -import-instr-limit=7 -thinlto-index combined.index.bc main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=DUMP - -; DUMP: - 2 function definitions and 3 function declarations imported from lib.bc - -; First disassemble per-module summary and find out the GUID for {large_func, large_indirect_callee}. -; -; RUN: llvm-dis lib.bc -o - | FileCheck %s --check-prefix=LIB-DIS -; LIB-DIS: [[LARGEFUNC:\^[0-9]+]] = gv: (name: "large_func", summaries: {{.*}}) ; guid = 2418497564662708935 -; LIB-DIS: [[LARGEINDIRECT:\^[0-9]+]] = gv: (name: "large_indirect_callee", summaries: {{.*}}) ; guid = 14343440786664691134 -; LIB-DIS: [[LARGEINDIRECTALIAS:\^[0-9]+]] = gv: (name: "large_indirect_callee_alias", summaries: {{.*}}, aliasee: [[LARGEINDIRECT]] -; -; Secondly disassemble main's combined summary and test that large callees are -; not imported as declarations yet. -; -; RUN: llvm-dis main.bc.thinlto.bc -o - | FileCheck %s --check-prefix=MAIN-DIS -; -; MAIN-DIS: [[LIBMOD:\^[0-9]+]] = module: (path: "lib.bc", hash: (0, 0, 0, 0, 0)) -; MAIN-DIS-NOT: [[LARGEFUNC:\^[0-9]+]] = gv: (guid: 2418497564662708935, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}}))) -; MAIN-DIS-NOT: [[LARGEINDIRECT:\^[0-9]+]] = gv: (guid: 14343440786664691134, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}}))) -; MAIN-DIS-NOT: [[LARGEINDIRECTALIAS:\^[0-9]+]] = gv: (guid: 16730173943625350469, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration) - -; Run in-process ThinLTO and tests that -; 1. `callee` remains internalized even if the symbols of its callers -; (large_func and large_indirect_callee) are exported as declarations and visible to main module. -; 2. the debugging logs from `function-import` pass are expected. - -; RUN: llvm-lto2 run \ -; RUN: -debug-only=function-import \ -; RUN: -save-temps \ -; RUN: -import-instr-limit=7 \ -; RUN: -import-declaration \ -; RUN: -r=main.bc,main,px \ -; RUN: -r=main.bc,small_func, \ -; RUN: -r=main.bc,large_func, \ -; RUN: -r=lib.bc,callee,pl \ -; RUN: -r=lib.bc,large_indirect_callee,px \ -; RUN: -r=lib.bc,small_func,px \ -; RUN: -r=lib.bc,large_func,px \ -; RUN: -r=lib.bc,large_indirect_callee_alias,px \ -; RUN: -r=lib.bc,calleeAddrs,px -o in-process main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=IMPORTDUMP - -; Test import status from debugging logs. -; TODO: Serialize declaration bit and test declaration bits are correctly set, -; and extend this test case to test IR once postlink optimizer makes use of -; the import type for declarations. -; IMPORTDUMP-DAG: Not importing function 11825436545918268459 callee from lib.cc -; IMPORTDUMP-DAG: Is importing function declaration 14343440786664691134 large_indirect_callee from lib.cc -; IMPORTDUMP-DAG: Is importing function definition 13568239288960714650 small_indirect_callee from lib.cc -; IMPORTDUMP-DAG: Is importing function definition 6976996067367342685 small_func from lib.cc -; IMPORTDUMP-DAG: Is importing function declaration 2418497564662708935 large_func from lib.cc -; IMPORTDUMP-DAG: Not importing global 7680325410415171624 calleeAddrs from lib.cc -; IMPORTDUMP-DAG: Is importing alias declaration 16730173943625350469 large_indirect_callee_alias from lib.cc - -; RUN: llvm-dis in-process.1.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT - -; RUN: llvm-dis in-process.2.2.internalize.bc -o - | FileCheck %s --check-prefix=INTERNALIZE - -; IMPORT-DAG: define available_externally void @small_func -; IMPORT-DAG: define available_externally hidden void @small_indirect_callee -; IMPORT-DAG: declare void @large_func -; IMPORT-NOT: large_indirect_callee -; IMPORT-NOT: large_indirect_callee_alias - -; INTERNALIZE: define internal void @callee() - -;--- main.ll -target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" -target triple = "x86_64-unknown-linux-gnu" - -define i32 @main() { - call void @small_func() - call void @large_func() - ret i32 0 -} - -declare void @small_func() - -; large_func without attributes -declare void @large_func() - -;--- lib.ll -source_filename = "lib.cc" -target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" -target triple = "x86_64-unknown-linux-gnu" - -@calleeAddrs = global [3 x ptr] [ptr @large_indirect_callee, ptr @small_indirect_callee, ptr @large_indirect_callee_alias] - -define void @callee() #1 { - ret void -} - -define void @large_indirect_callee()#2 { - call void @callee() - call void @callee() - call void @callee() - call void @callee() - call void @callee() - call void @callee() - call void @callee() - ret void -} - -define internal void @small_indirect_callee() #0 { - ret void -} - -@large_indirect_callee_alias = alias void(), ptr @large_indirect_callee - -define void @small_func() { -entry: - %0 = load ptr, ptr @calleeAddrs - call void %0(), !prof !0 - %1 = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @calleeAddrs, i64 0, i64 1) - call void %1(), !prof !1 - %2 = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @calleeAddrs, i64 0, i64 2) - call void %2(), !prof !2 - ret void -} - -define void @large_func() #0 { -entry: - call void @callee() - call void @callee() - call void @callee() - call void @callee() - call void @callee() - call void @callee() - call void @callee() - ret void -} - -attributes #0 = { nounwind norecurse } - -attributes #1 = { noinline } - -attributes #2 = { norecurse } - -!0 = !{!"VP", i32 0, i64 1, i64 14343440786664691134, i64 1} -!1 = !{!"VP", i32 0, i64 1, i64 13568239288960714650, i64 1} -!2 = !{!"VP", i32 0, i64 1, i64 16730173943625350469, i64 1} diff --git a/llvm/test/Transforms/FunctionImport/funcimport.ll b/llvm/test/Transforms/FunctionImport/funcimport.ll index 635750b33fff..a0968a67f5ce 100644 --- a/llvm/test/Transforms/FunctionImport/funcimport.ll +++ b/llvm/test/Transforms/FunctionImport/funcimport.ll @@ -166,8 +166,7 @@ declare void @variadic_va_start(...) ; GUID-DAG: GUID {{.*}} is linkoncefunc ; DUMP: Module [[M1:.*]] imports from 1 module -; DUMP-NEXT: 15 function definitions and 0 function declarations imported from [[M2:.*]] -; DUMP-NEXT: 4 var definitions and 0 var declarations imported from [[M2]] - +; DUMP-NEXT: 15 functions imported from [[M2:.*]] +; DUMP-NEXT: 4 vars imported from [[M2]] ; DUMP: Imported 15 functions for Module [[M1]] ; DUMP-NEXT: Imported 4 global variables for Module [[M1]] diff --git a/llvm/tools/llvm-link/llvm-link.cpp b/llvm/tools/llvm-link/llvm-link.cpp index 1b90fce76fbd..7794f2d81ed0 100644 --- a/llvm/tools/llvm-link/llvm-link.cpp +++ b/llvm/tools/llvm-link/llvm-link.cpp @@ -377,13 +377,9 @@ static bool importFunctions(const char *argv0, Module &DestModule) { if (Verbose) errs() << "Importing " << FunctionName << " from " << FileName << "\n"; - // `-import` specifies the `` pairs to import as - // definition, so make the import type definition directly. - // FIXME: A follow-up patch should add test coverage for import declaration - // in `llvm-link` CLI (e.g., by introducing a new command line option). auto &Entry = ImportList[FileNameStringCache.insert(FileName).first->getKey()]; - Entry[F->getGUID()] = GlobalValueSummary::Definition; + Entry.insert(F->getGUID()); } auto CachedModuleLoader = [&](StringRef Identifier) { return ModuleLoaderCache.takeModule(std::string(Identifier)); -- GitLab From 32ae9a28a54f59f2b4e2f32323f53fb107ea1f85 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Sun, 19 May 2024 22:48:06 -0700 Subject: [PATCH 055/793] [llvm] Use SmallString::str (NFC) (#92712) --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 2 +- llvm/lib/CodeGen/ParallelCG.cpp | 4 +--- llvm/lib/LTO/LTOBackend.cpp | 5 ++--- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index e64051cf5386..c9295344f808 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2940,7 +2940,7 @@ Error BitcodeReader::parseValueSymbolTable(uint64_t Offset) { if (!BB) return error("Invalid bbentry record"); - BB->setName(StringRef(ValueName.data(), ValueName.size())); + BB->setName(ValueName.str()); ValueName.clear(); break; } diff --git a/llvm/lib/CodeGen/ParallelCG.cpp b/llvm/lib/CodeGen/ParallelCG.cpp index ceb64b2badab..8ab64f8afe6e 100644 --- a/llvm/lib/CodeGen/ParallelCG.cpp +++ b/llvm/lib/CodeGen/ParallelCG.cpp @@ -79,9 +79,7 @@ void llvm::splitCodeGen( [TMFactory, FileType, ThreadOS](const SmallString<0> &BC) { LLVMContext Ctx; Expected> MOrErr = parseBitcodeFile( - MemoryBufferRef(StringRef(BC.data(), BC.size()), - ""), - Ctx); + MemoryBufferRef(BC.str(), ""), Ctx); if (!MOrErr) report_fatal_error("Failed to read bitcode"); std::unique_ptr MPartInCtx = std::move(MOrErr.get()); diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp index d4b89ede2d71..21aed799d6fa 100644 --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -452,9 +452,8 @@ static void splitCodeGen(const Config &C, TargetMachine *TM, CodegenThreadPool.async( [&](const SmallString<0> &BC, unsigned ThreadId) { LTOLLVMContext Ctx(C); - Expected> MOrErr = parseBitcodeFile( - MemoryBufferRef(StringRef(BC.data(), BC.size()), "ld-temp.o"), - Ctx); + Expected> MOrErr = + parseBitcodeFile(MemoryBufferRef(BC.str(), "ld-temp.o"), Ctx); if (!MOrErr) report_fatal_error("Failed to read bitcode"); std::unique_ptr MPartInCtx = std::move(MOrErr.get()); -- GitLab From 7529fe2e92e79eef22a528a7168e4dd777d6e9bd Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Mon, 20 May 2024 07:08:40 +0100 Subject: [PATCH 056/793] [AMDGPU] Only set Info.memVT when not later overridden (#92670) For the amdgcn_*_buffer_load_lds intrinsics this field is later overriden, so avoid pointlessly calling MVT::getVT in that case. Importantly, this is also the only case I can find in tree where a PointerType is passed to MVT::getVT, so this will allow us to forbid doing so in future, keeping MVT::iPTR as originating solely from TableGen as was claimed next to its definition in MachineValueType.h (but lost in the autogeneration conversion). --- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index c7c4a8faa2fb..d7b6941fcf81 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -1233,13 +1233,13 @@ bool SITargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info, // Atomic Info.opc = CI.getType()->isVoidTy() ? ISD::INTRINSIC_VOID : ISD::INTRINSIC_W_CHAIN; - Info.memVT = MVT::getVT(CI.getArgOperand(0)->getType()); Info.flags |= MachineMemOperand::MOLoad | MachineMemOperand::MOStore | MachineMemOperand::MODereferenceable; switch (IntrID) { default: + Info.memVT = MVT::getVT(CI.getArgOperand(0)->getType()); // XXX - Should this be volatile without known ordering? Info.flags |= MachineMemOperand::MOVolatile; break; -- GitLab From 9500a5d02e23f9b43294e5f662ac099f8989c0e4 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 19 May 2024 23:35:15 -0700 Subject: [PATCH 057/793] [MC] Make UseAssemblerInfoForParsing mostly true Commit 6c0665e22174d474050e85ca367424f6e02476be (https://reviews.llvm.org/D45164) enabled certain constant expression evaluation for `MCObjectStreamer` at parse time (e.g. `.if` directives, see llvm/test/MC/AsmParser/assembler-expressions.s). `getUseAssemblerInfoForParsing` was added to make `clang -c` handling inline assembly similar to `MCAsmStreamer` (e.g. `llvm-mc -filetype=asm`), where such expression folding (related to `AttemptToFoldSymbolOffsetDifference`) is unavailable. I believe this is overly conservative. We can make some parse-time expression folding work for `clang -c` even if `clang -S` would still report an error, a MCAsmStreamer issue (we cannot print `.if` directives) that should not restrict the functionality of MCObjectStreamer. ``` % cat b.cc asm(R"( .pushsection .text,"ax" .globl _start; _start: ret .if . -_start == 1 ret .endif .popsection )"); % gcc -S b.cc && gcc -c b.cc % clang -S -fno-integrated-as b.cc # succeeded % clang -c b.cc # succeeded with this patch % clang -S b.cc # still failed :4:5: error: expected absolute expression 4 | .if . -_start == 1 | ^ 1 error generated. ``` However, removing `getUseAssemblerInfoForParsing` would make MCDwarfFrameEmitter::Emit (for .eh_frame FDE) slow (~4% compile time regression for sqlite3.c amalgamation) due to expensive `AttemptToFoldSymbolOffsetDifference`. For now, make `UseAssemblerInfoForParsing` false in MCDwarfFrameEmitter::Emit. Close #62520 Link: https://discourse.llvm.org/t/rfc-clang-assembly-object-equivalence-for-files-with-inline-assembly/78841 Pull Request: https://github.com/llvm/llvm-project/pull/91082 --- clang/tools/driver/cc1as_main.cpp | 3 --- llvm/include/llvm/MC/MCStreamer.h | 4 +++- .../CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp | 3 --- llvm/lib/MC/MCDwarf.cpp | 6 ++++++ llvm/lib/MC/MCObjectStreamer.cpp | 3 --- llvm/lib/MC/MCStreamer.cpp | 2 +- llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp | 7 ++----- llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp | 3 --- .../AsmParser/assembler-expressions-inlineasm.ll | 16 ++++++++++------ llvm/tools/llvm-mc/llvm-mc.cpp | 3 --- llvm/tools/llvm-ml/llvm-ml.cpp | 3 --- 11 files changed, 22 insertions(+), 31 deletions(-) diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index 86afe22fac24..4eb753a7297a 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -576,9 +576,6 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, Str.get()->emitZeros(1); } - // Assembly to object compilation should leverage assembly info. - Str->setUseAssemblerInfoForParsing(true); - bool Failed = false; std::unique_ptr Parser( diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 69867620e1bf..b7468cf70a66 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -245,7 +245,7 @@ class MCStreamer { /// requires. unsigned NextWinCFIID = 0; - bool UseAssemblerInfoForParsing; + bool UseAssemblerInfoForParsing = true; /// Is the assembler allowed to insert padding automatically? For /// correctness reasons, we sometimes need to ensure instructions aren't @@ -296,6 +296,8 @@ public: MCContext &getContext() const { return Context; } + // MCObjectStreamer has an MCAssembler and allows more expression folding at + // parse time. virtual MCAssembler *getAssemblerPtr() { return nullptr; } void setUseAssemblerInfoForParsing(bool v) { UseAssemblerInfoForParsing = v; } diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index d0ef3e5a1939..08e3c208ba4d 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -102,9 +102,6 @@ void AsmPrinter::emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, std::unique_ptr Parser( createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI, BufNum)); - // Do not use assembler-level information for parsing inline assembly. - OutStreamer->setUseAssemblerInfoForParsing(false); - // We create a new MCInstrInfo here since we might be at the module level // and not have a MachineFunction to initialize the TargetInstrInfo from and // we only need MCInstrInfo for asm parsing. We create one unconditionally diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp index 2ee0c3eb27b9..aba4071e6b91 100644 --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -1910,6 +1910,11 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, [](const MCDwarfFrameInfo &X, const MCDwarfFrameInfo &Y) { return CIEKey(X) < CIEKey(Y); }); + // Disable AttemptToFoldSymbolOffsetDifference folding of fdeStart-cieStart + // for EmitFDE due to the the performance issue. The label differences will be + // evaluate at write time. + assert(Streamer.getUseAssemblerInfoForParsing()); + Streamer.setUseAssemblerInfoForParsing(false); for (auto I = FrameArrayX.begin(), E = FrameArrayX.end(); I != E;) { const MCDwarfFrameInfo &Frame = *I; ++I; @@ -1930,6 +1935,7 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, Emitter.EmitFDE(*CIEStart, Frame, I == E, *SectionStart); } + Streamer.setUseAssemblerInfoForParsing(true); } void MCDwarfFrameEmitter::encodeAdvanceLoc(MCContext &Context, diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index d2da5d0d3f90..0ccade91677a 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -40,9 +40,6 @@ MCObjectStreamer::MCObjectStreamer(MCContext &Context, MCObjectStreamer::~MCObjectStreamer() = default; -// AssemblerPtr is used for evaluation of expressions and causes -// difference between asm and object outputs. Return nullptr to in -// inline asm mode to limit divergence to assembly inputs. MCAssembler *MCObjectStreamer::getAssemblerPtr() { if (getUseAssemblerInfoForParsing()) return Assembler.get(); diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index 176d55aa890b..199d865ea349 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -93,7 +93,7 @@ void MCTargetStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {} MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx), CurrentWinFrameInfo(nullptr), - CurrentProcWinFrameInfoStartIndex(0), UseAssemblerInfoForParsing(false) { + CurrentProcWinFrameInfoStartIndex(0) { SectionStack.push_back(std::pair()); } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp index b7388ed9e85a..bd48a5f80c82 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp @@ -517,12 +517,9 @@ bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) { DumpCodeInstEmitter = nullptr; if (STM.dumpCode()) { - // For -dumpcode, get the assembler out of the streamer, even if it does - // not really want to let us have it. This only works with -filetype=obj. - bool SaveFlag = OutStreamer->getUseAssemblerInfoForParsing(); - OutStreamer->setUseAssemblerInfoForParsing(true); + // For -dumpcode, get the assembler out of the streamer. This only works + // with -filetype=obj. MCAssembler *Assembler = OutStreamer->getAssemblerPtr(); - OutStreamer->setUseAssemblerInfoForParsing(SaveFlag); if (Assembler) DumpCodeInstEmitter = Assembler->getEmitterPtr(); } diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp index 2ebe5bdc4771..ad0158086044 100644 --- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp @@ -114,12 +114,9 @@ void SPIRVAsmPrinter::emitEndOfAsmFile(Module &M) { // Bound is an approximation that accounts for the maximum used register // number and number of generated OpLabels unsigned Bound = 2 * (ST->getBound() + 1) + NLabels; - bool FlagToRestore = OutStreamer->getUseAssemblerInfoForParsing(); - OutStreamer->setUseAssemblerInfoForParsing(true); if (MCAssembler *Asm = OutStreamer->getAssemblerPtr()) Asm->setBuildVersion(static_cast(0), Major, Minor, Bound, VersionTuple(Major, Minor, 0, Bound)); - OutStreamer->setUseAssemblerInfoForParsing(FlagToRestore); } void SPIRVAsmPrinter::emitFunctionHeader() { diff --git a/llvm/test/MC/AsmParser/assembler-expressions-inlineasm.ll b/llvm/test/MC/AsmParser/assembler-expressions-inlineasm.ll index 35f110f37e2f..9d9a38f5b5a5 100644 --- a/llvm/test/MC/AsmParser/assembler-expressions-inlineasm.ll +++ b/llvm/test/MC/AsmParser/assembler-expressions-inlineasm.ll @@ -1,13 +1,17 @@ -; RUN: not llc -mtriple x86_64-unknown-linux-gnu -o %t.s -filetype=asm %s 2>&1 | FileCheck %s -; RUN: not llc -mtriple x86_64-unknown-linux-gnu -o %t.o -filetype=obj %s 2>&1 | FileCheck %s - -; Assembler-aware expression evaluation should be disabled in inline -; assembly to prevent differences in behavior between object and -; assembly output. +; RUN: not llc -mtriple=x86_64 %s -o /dev/null 2>&1 | FileCheck %s +; RUN: llc -mtriple=x86_64 -no-integrated-as < %s | FileCheck %s --check-prefix=GAS +; RUN: llc -mtriple=x86_64 -filetype=obj %s -o - | llvm-objdump -d - | FileCheck %s --check-prefix=DISASM +; GAS: nop; .if . - foo==1; nop;.endif ; CHECK: :1:17: error: expected absolute expression +; DISASM:
: +; DISASM-NEXT: nop +; DISASM-NEXT: nop +; DISASM-NEXT: xorl %eax, %eax +; DISASM-NEXT: retq + define i32 @main() local_unnamed_addr { tail call void asm sideeffect "foo: nop; .if . - foo==1; nop;.endif", "~{dirflag},~{fpsr},~{flags}"() ret i32 0 diff --git a/llvm/tools/llvm-mc/llvm-mc.cpp b/llvm/tools/llvm-mc/llvm-mc.cpp index 807071a7b9a1..506e4f22ef8f 100644 --- a/llvm/tools/llvm-mc/llvm-mc.cpp +++ b/llvm/tools/llvm-mc/llvm-mc.cpp @@ -569,9 +569,6 @@ int main(int argc, char **argv) { Str->initSections(true, *STI); } - // Use Assembler information for parsing. - Str->setUseAssemblerInfoForParsing(true); - int Res = 1; bool disassemble = false; switch (Action) { diff --git a/llvm/tools/llvm-ml/llvm-ml.cpp b/llvm/tools/llvm-ml/llvm-ml.cpp index 1cac576f54e7..f1f39af059aa 100644 --- a/llvm/tools/llvm-ml/llvm-ml.cpp +++ b/llvm/tools/llvm-ml/llvm-ml.cpp @@ -428,9 +428,6 @@ int llvm_ml_main(int Argc, char **Argv, const llvm::ToolContext &) { Str->emitAssignment(Feat00Sym, MCConstantExpr::create(Feat00Flags, Ctx)); } - // Use Assembler information for parsing. - Str->setUseAssemblerInfoForParsing(true); - int Res = 1; if (InputArgs.hasArg(OPT_as_lex)) { // -as-lex; Lex only, and output a stream of tokens -- GitLab From eac743d1b01fd44bc742e1ccc2be8360908bdbf8 Mon Sep 17 00:00:00 2001 From: YunQiang Su Date: Mon, 20 May 2024 14:46:47 +0800 Subject: [PATCH 058/793] MIPS: Support '%w' token in inline asm template for MSA (#91920) MSA registers share the FPRs as its bottom half. So that we can use MSA instructions to work with normal float/double: double a, b, c; asm volatile ("fmadd.d %w0, %w1, %w2" : "+f"(a) : "f"(b), "f"(c)); GCC has support it for quite long time. --- llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h | 9 +++++++++ llvm/lib/Target/Mips/MipsAsmPrinter.cpp | 11 +++++++---- llvm/test/CodeGen/Mips/msa/inline-asm.ll | 16 ++++++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h index 02ab5ede2c1a..aa35e7db6bda 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -135,6 +135,15 @@ namespace MipsII { OPERAND_LAST_MIPS_MEM_IMM = OPERAND_MEM_SIMM9 }; } + +inline static MCRegister getMSARegFromFReg(MCRegister Reg) { + if (Reg >= Mips::F0 && Reg <= Mips::F31) + return Reg - Mips::F0 + Mips::W0; + else if (Reg >= Mips::D0_64 && Reg <= Mips::D31_64) + return Reg - Mips::D0_64 + Mips::W0; + else + return Mips::NoRegister; +} } #endif diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index 66b2b0de8d52..dda33f9a1808 100644 --- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -565,12 +565,15 @@ bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, } break; } - case 'w': - // Print MSA registers for the 'f' constraint - // In LLVM, the 'w' modifier doesn't need to do anything. - // We can just call printOperand as normal. + case 'w': { + MCRegister w = getMSARegFromFReg(MO.getReg()); + if (w != Mips::NoRegister) { + O << '$' << MipsInstPrinter::getRegisterName(w); + return false; + } break; } + } } printOperand(MI, OpNum, O); diff --git a/llvm/test/CodeGen/Mips/msa/inline-asm.ll b/llvm/test/CodeGen/Mips/msa/inline-asm.ll index 57cd78a25647..f84b11e05387 100644 --- a/llvm/test/CodeGen/Mips/msa/inline-asm.ll +++ b/llvm/test/CodeGen/Mips/msa/inline-asm.ll @@ -32,3 +32,19 @@ entry: store <4 x i32> %1, ptr @v4i32_r ret void } + +define dso_local double @test4(double noundef %a, double noundef %b, double noundef %c) { +entry: + ; CHECK-LABEL: test4: + %0 = tail call double asm sideeffect "fmadd.d ${0:w}, ${1:w}, ${2:w}", "=f,f,f,0,~{$1}"(double %b, double %c, double %a) + ; CHECK: fmadd.d $w{{([0-9]|[1-3][0-9])}}, $w{{([0-9]|[1-3][0-9])}}, $w{{([0-9]|[1-3][0-9])}} + ret double %0 +} + +define dso_local float @test5(float noundef %a, float noundef %b, float noundef %c) { +entry: + ; CHECK-LABEL: test5: + %0 = tail call float asm sideeffect "fmadd.w ${0:w}, ${1:w}, ${2:w}", "=f,f,f,0,~{$1}"(float %b, float %c, float %a) + ; CHECK: fmadd.w $w{{([0-9]|[1-3][0-9])}}, $w{{([0-9]|[1-3][0-9])}}, $w{{([0-9]|[1-3][0-9])}} + ret float %0 +} -- GitLab From d59bc6b5c75384aa0b1e78cc85e17e8acaccebaf Mon Sep 17 00:00:00 2001 From: YunQiang Su Date: Mon, 20 May 2024 14:48:34 +0800 Subject: [PATCH 059/793] Clang/MIPS: Add +fp64 if MSA and no explicit -mfp option (#91949) MSA requires -mfp64. If FP64 is supported by CPU (mips32r2+), and no -mfp32/-mfpxx is explicitly given, let's add +fp64. Otherwise some cmd like clang --target=mips -mips32r5 -mmsa will issue LLVM backend ICE. --- clang/lib/Driver/ToolChains/Arch/Mips.cpp | 10 ++++++++++ clang/test/Driver/mips-as.c | 2 +- clang/test/Driver/mips-features.c | 6 ++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/clang/lib/Driver/ToolChains/Arch/Mips.cpp b/clang/lib/Driver/ToolChains/Arch/Mips.cpp index 74a8874a3ea2..79a00711e6f5 100644 --- a/clang/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/clang/lib/Driver/ToolChains/Arch/Mips.cpp @@ -369,6 +369,9 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, } else if (mips::isFP64ADefault(Triple, CPUName)) { Features.push_back("+fp64"); Features.push_back("+nooddspreg"); + } else if (Arg *A = Args.getLastArg(options::OPT_mmsa)) { + if (A->getOption().matches(options::OPT_mmsa)) + Features.push_back("+fp64"); } AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg, @@ -499,6 +502,13 @@ bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple, options::OPT_mdouble_float)) if (A->getOption().matches(options::OPT_msingle_float)) UseFPXX = false; + // FP64 should be used for MSA. + if (Arg *A = Args.getLastArg(options::OPT_mmsa)) + if (A->getOption().matches(options::OPT_mmsa)) + UseFPXX = llvm::StringSwitch(CPUName) + .Cases("mips32r2", "mips32r3", "mips32r5", false) + .Cases("mips64r2", "mips64r3", "mips64r5", false) + .Default(UseFPXX); return UseFPXX; } diff --git a/clang/test/Driver/mips-as.c b/clang/test/Driver/mips-as.c index 14fbb18c9350..a3399f1078fc 100644 --- a/clang/test/Driver/mips-as.c +++ b/clang/test/Driver/mips-as.c @@ -266,7 +266,7 @@ // RUN: %clang -target mips-linux-gnu -mno-msa -mmsa -### \ // RUN: -no-integrated-as -fno-pic -c %s 2>&1 \ // RUN: | FileCheck -check-prefix=MIPS-MSA %s -// MIPS-MSA: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-mno-shared" "-call_nonpic" "-EB" "-mfpxx" "-mmsa" +// MIPS-MSA: as{{(.exe)?}}" "-march" "mips32r2" "-mabi" "32" "-mno-shared" "-call_nonpic" "-EB" "-mmsa" // // RUN: %clang -target mips-linux-gnu -mmsa -mno-msa -### \ // RUN: -no-integrated-as -fno-pic -c %s 2>&1 \ diff --git a/clang/test/Driver/mips-features.c b/clang/test/Driver/mips-features.c index 5e92dccaa02a..8b8db4c4a341 100644 --- a/clang/test/Driver/mips-features.c +++ b/clang/test/Driver/mips-features.c @@ -163,6 +163,12 @@ // RUN: | FileCheck --check-prefix=CHECK-NOMMSA %s // CHECK-NOMMSA: "-target-feature" "-msa" // +// -mmsa +// RUN: %clang -target mips-linux-gnu -### -c %s \ +// RUN: -mmsa 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-MMSA-MFP64 %s +// CHECK-MMSA-MFP64: "-target-feature" "+msa" "-target-feature" "+fp64" +// // -mmt // RUN: %clang -target mips-linux-gnu -### -c %s \ // RUN: -mno-mt -mmt 2>&1 \ -- GitLab From 073488cb1f2ca131253efa3171bd56be34ba9fb3 Mon Sep 17 00:00:00 2001 From: YunQiang Su Date: Mon, 20 May 2024 14:50:26 +0800 Subject: [PATCH 060/793] MIPS/Clang: Use FP32 by default if CPU is mips1 (#92122) FP32 is the only supported FPMode of mips1. FPXX requires MIPS2+ and FP64 requires MIPS32r2+. --- clang/lib/Basic/Targets/Mips.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/clang/lib/Basic/Targets/Mips.h b/clang/lib/Basic/Targets/Mips.h index 730deb674aa5..f76c6ece8bf4 100644 --- a/clang/lib/Basic/Targets/Mips.h +++ b/clang/lib/Basic/Targets/Mips.h @@ -85,8 +85,13 @@ public: return CPU == "mips32r6" || CPU == "mips64r6"; } - bool isFP64Default() const { - return CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64"; + enum FPModeEnum getDefaultFPMode() const { + if (CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64") + return FP64; + else if (CPU == "mips1") + return FP32; + else + return FPXX; } bool isNan2008() const override { return IsNan2008; } @@ -315,8 +320,8 @@ public: IsSingleFloat = false; FloatABI = HardFloat; DspRev = NoDSP; - FPMode = isFP64Default() ? FP64 : FPXX; NoOddSpreg = false; + FPMode = getDefaultFPMode(); bool OddSpregGiven = false; bool StrictAlign = false; -- GitLab From dd8cb3d4f120edcf5fc3939594ee086c44010274 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 20 May 2024 00:13:09 -0700 Subject: [PATCH 061/793] [ELF] Support high address DW_EH_sdata4 for ELFCLASS32 When the address pointer encoding in FDEs uses DW_EH_PE_absptr|DW_EH_PE_sdata4, the address is sign-extended to 64-bit by `readFdeAddr`. We should truncate the address to 32-bit for ELFCLASS32. Otherwise, `isInt<32>(pc - va)` could be false, leading to a spurious error in `getFdeData`. In LLVM, this appears a MIPS-specific issue. Fix #88852 Pull Request: https://github.com/llvm/llvm-project/pull/92438 --- lld/ELF/SyntheticSections.cpp | 2 +- lld/test/ELF/mips-eh_frame-pic.s | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 22bfed0852bc..ad280289cebf 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -613,7 +613,7 @@ uint64_t EhFrameSection::getFdePc(uint8_t *buf, size_t fdeOff, size_t off = fdeOff + 8; uint64_t addr = readFdeAddr(buf + off, enc & 0xf); if ((enc & 0x70) == DW_EH_PE_absptr) - return addr; + return config->is64 ? addr : uint32_t(addr); if ((enc & 0x70) == DW_EH_PE_pcrel) return addr + getParent()->addr + off + outSecOff; fatal("unknown FDE size relative encoding"); diff --git a/lld/test/ELF/mips-eh_frame-pic.s b/lld/test/ELF/mips-eh_frame-pic.s index 79076e74a7e3..fd8560bc0163 100644 --- a/lld/test/ELF/mips-eh_frame-pic.s +++ b/lld/test/ELF/mips-eh_frame-pic.s @@ -27,6 +27,11 @@ ## relative addressing. # NOPIC32-ERR: ld.lld: error: relocation R_MIPS_32 cannot be used against local symbol +## https://github.com/llvm/llvm-project/issues/88852: getFdePc should return a +## 32-bit address. +# RUN: ld.lld --eh-frame-hdr -Ttext=0x80000000 %t-nopic32.o -o %t-nopic32 +# RUN: llvm-readelf -x .eh_frame_hdr %t-nopic32 | FileCheck %s --check-prefix=NOPIC32-HDR + ## For -fPIC, .eh_frame should contain DW_EH_PE_pcrel | DW_EH_PE_sdata4 values: # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux --position-independent %s -o %t-pic32.o # RUN: llvm-readobj -r %t-pic32.o | FileCheck %s --check-prefixes=RELOCS,PIC32-RELOCS @@ -51,6 +56,10 @@ ## Note: ld.bfd converts the R_MIPS_64 relocs to DW_EH_PE_pcrel | DW_EH_PE_sdata8 ## for N64 ABI (and DW_EH_PE_pcrel | DW_EH_PE_sdata4 for MIPS32) +# NOPIC32-HDR: Hex dump of section '.eh_frame_hdr': +# NOPIC32-HDR: 0x80010038 011b033b 00000010 00000001 fffeffc8 . +# NOPIC32-HDR: 0x80010048 00000028 . + .ent func .global func func: -- GitLab From 2143b7cd7d184b3f3bc4a997ea925ab7574c93f9 Mon Sep 17 00:00:00 2001 From: Chen Zheng Date: Mon, 20 May 2024 03:10:08 -0400 Subject: [PATCH 062/793] [PowerPC]perform bitcast lowering only at 64 bit Perform bitcast lowering requires 64-bit to be native supported, However this is not true on 32-bit targets. Explicitly require 64-bit target. Fixes #92233 --- llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 2 +- llvm/test/CodeGen/PowerPC/pr92233.ll | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/PowerPC/pr92233.ll diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index ad86c393ba79..8450ce9e0e3b 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -9338,7 +9338,7 @@ SDValue PPCTargetLowering::LowerBITCAST(SDValue Op, SelectionDAG &DAG) const { if ((Op.getValueType() != MVT::f128) || (Op0.getOpcode() != ISD::BUILD_PAIR) || (Op0.getOperand(0).getValueType() != MVT::i64) || - (Op0.getOperand(1).getValueType() != MVT::i64)) + (Op0.getOperand(1).getValueType() != MVT::i64) || !Subtarget.isPPC64()) return SDValue(); return DAG.getNode(PPCISD::BUILD_FP128, dl, MVT::f128, Op0.getOperand(0), diff --git a/llvm/test/CodeGen/PowerPC/pr92233.ll b/llvm/test/CodeGen/PowerPC/pr92233.ll new file mode 100644 index 000000000000..858d665909fe --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/pr92233.ll @@ -0,0 +1,19 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mcpu=pwr9 -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu | FileCheck %s + +define internal fp128 @f(i128 %v) nounwind { +; CHECK-LABEL: f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: stwu 1, -32(1) +; CHECK-NEXT: stw 6, 28(1) +; CHECK-NEXT: stw 5, 24(1) +; CHECK-NEXT: stw 4, 20(1) +; CHECK-NEXT: stw 3, 16(1) +; CHECK-NEXT: lxv 34, 16(1) +; CHECK-NEXT: addi 1, 1, 32 +; CHECK-NEXT: blr +entry: + %cast = bitcast i128 %v to fp128 + ret fp128 %cast +} + -- GitLab From a027bea438e285380450f5b380be072f44ee0312 Mon Sep 17 00:00:00 2001 From: hev Date: Mon, 20 May 2024 15:24:52 +0800 Subject: [PATCH 063/793] [LoongArch] Select {DIV,MOD}.{W,WU} instruction to eliminate explicit sign extension (#92205) --- .../LoongArch/LoongArchISelLowering.cpp | 13 +++ .../Target/LoongArch/LoongArchISelLowering.h | 4 + .../Target/LoongArch/LoongArchInstrInfo.td | 6 ++ .../ir-instruction/sdiv-udiv-srem-urem.ll | 96 +++++++------------ 4 files changed, 57 insertions(+), 62 deletions(-) diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index fe2c613b1b30..8a87c82a205b 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -139,6 +139,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM, setOperationAction(ISD::BITREVERSE, MVT::i32, Custom); setOperationAction(ISD::BSWAP, MVT::i32, Custom); + setOperationAction({ISD::UDIV, ISD::UREM}, MVT::i32, Custom); } // Set operations for LA32 only. @@ -1665,6 +1666,10 @@ static LoongArchISD::NodeType getLoongArchWOpcode(unsigned Opcode) { switch (Opcode) { default: llvm_unreachable("Unexpected opcode"); + case ISD::UDIV: + return LoongArchISD::DIV_WU; + case ISD::UREM: + return LoongArchISD::MOD_WU; case ISD::SHL: return LoongArchISD::SLL_W; case ISD::SRA: @@ -1841,6 +1846,12 @@ void LoongArchTargetLowering::ReplaceNodeResults( switch (N->getOpcode()) { default: llvm_unreachable("Don't know how to legalize this operation"); + case ISD::UDIV: + case ISD::UREM: + assert(VT == MVT::i32 && Subtarget.is64Bit() && + "Unexpected custom legalisation"); + Results.push_back(customLegalizeToWOp(N, DAG, 2, ISD::SIGN_EXTEND)); + break; case ISD::SHL: case ISD::SRA: case ISD::SRL: @@ -3445,6 +3456,8 @@ const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const { NODE_NAME_CASE(BITREV_W) NODE_NAME_CASE(ROTR_W) NODE_NAME_CASE(ROTL_W) + NODE_NAME_CASE(DIV_WU) + NODE_NAME_CASE(MOD_WU) NODE_NAME_CASE(CLZ_W) NODE_NAME_CASE(CTZ_W) NODE_NAME_CASE(DBAR) diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h index de3f45172e25..f274b1971fd2 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h @@ -43,6 +43,10 @@ enum NodeType : unsigned { ROTL_W, ROTR_W, + // unsigned 32-bit integer division + DIV_WU, + MOD_WU, + // FPR<->GPR transfer operations MOVGR2FR_W_LA64, MOVFR2GR_S_LA64, diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td index f56f8f7e1179..35ea9f07866d 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td @@ -85,6 +85,8 @@ def loongarch_sll_w : SDNode<"LoongArchISD::SLL_W", SDT_LoongArchIntBinOpW>; def loongarch_sra_w : SDNode<"LoongArchISD::SRA_W", SDT_LoongArchIntBinOpW>; def loongarch_srl_w : SDNode<"LoongArchISD::SRL_W", SDT_LoongArchIntBinOpW>; def loongarch_rotr_w : SDNode<"LoongArchISD::ROTR_W", SDT_LoongArchIntBinOpW>; +def loongarch_div_wu : SDNode<"LoongArchISD::DIV_WU", SDT_LoongArchIntBinOpW>; +def loongarch_mod_wu : SDNode<"LoongArchISD::MOD_WU", SDT_LoongArchIntBinOpW>; def loongarch_crc_w_b_w : SDNode<"LoongArchISD::CRC_W_B_W", SDT_LoongArchIntBinOpW, [SDNPHasChain]>; def loongarch_crc_w_h_w @@ -1110,9 +1112,13 @@ def : PatGprImm_32; def : PatGprGpr; def : PatGprGpr_32; def : PatGprGpr; +def : PatGprGpr_32; def : PatGprGpr; +def : PatGprGpr; def : PatGprGpr; +def : PatGprGpr_32; def : PatGprGpr; +def : PatGprGpr; def : PatGprGpr; def : PatGprGpr; def : PatGprGpr_32; diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/sdiv-udiv-srem-urem.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/sdiv-udiv-srem-urem.ll index 2064c398948f..ab3eec240db3 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/sdiv-udiv-srem-urem.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/sdiv-udiv-srem-urem.ll @@ -191,8 +191,7 @@ define signext i32 @sdiv_si32_ui32_ui32(i32 %a, i32 %b) { ; LA64: # %bb.0: # %entry ; LA64-NEXT: addi.w $a1, $a1, 0 ; LA64-NEXT: addi.w $a0, $a0, 0 -; LA64-NEXT: div.d $a0, $a0, $a1 -; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: div.w $a0, $a0, $a1 ; LA64-NEXT: ret ; ; LA32-TRAP-LABEL: sdiv_si32_ui32_ui32: @@ -208,12 +207,11 @@ define signext i32 @sdiv_si32_ui32_ui32(i32 %a, i32 %b) { ; LA64-TRAP: # %bb.0: # %entry ; LA64-TRAP-NEXT: addi.w $a1, $a1, 0 ; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 -; LA64-TRAP-NEXT: div.d $a0, $a0, $a1 +; LA64-TRAP-NEXT: div.w $a0, $a0, $a1 ; LA64-TRAP-NEXT: bnez $a1, .LBB5_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 ; LA64-TRAP-NEXT: .LBB5_2: # %entry -; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 ; LA64-TRAP-NEXT: ret entry: %r = sdiv i32 %a, %b @@ -228,8 +226,7 @@ define signext i32 @sdiv_si32_si32_si32(i32 signext %a, i32 signext %b) { ; ; LA64-LABEL: sdiv_si32_si32_si32: ; LA64: # %bb.0: # %entry -; LA64-NEXT: div.d $a0, $a0, $a1 -; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: div.w $a0, $a0, $a1 ; LA64-NEXT: ret ; ; LA32-TRAP-LABEL: sdiv_si32_si32_si32: @@ -243,12 +240,11 @@ define signext i32 @sdiv_si32_si32_si32(i32 signext %a, i32 signext %b) { ; ; LA64-TRAP-LABEL: sdiv_si32_si32_si32: ; LA64-TRAP: # %bb.0: # %entry -; LA64-TRAP-NEXT: div.d $a0, $a0, $a1 +; LA64-TRAP-NEXT: div.w $a0, $a0, $a1 ; LA64-TRAP-NEXT: bnez $a1, .LBB6_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 ; LA64-TRAP-NEXT: .LBB6_2: # %entry -; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 ; LA64-TRAP-NEXT: ret entry: %r = sdiv i32 %a, %b @@ -407,9 +403,9 @@ define i32 @udiv_i32(i32 %a, i32 %b) { ; ; LA64-LABEL: udiv_i32: ; LA64: # %bb.0: # %entry -; LA64-NEXT: bstrpick.d $a1, $a1, 31, 0 -; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64-NEXT: div.du $a0, $a0, $a1 +; LA64-NEXT: addi.w $a1, $a1, 0 +; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: div.wu $a0, $a0, $a1 ; LA64-NEXT: ret ; ; LA32-TRAP-LABEL: udiv_i32: @@ -423,9 +419,9 @@ define i32 @udiv_i32(i32 %a, i32 %b) { ; ; LA64-TRAP-LABEL: udiv_i32: ; LA64-TRAP: # %bb.0: # %entry -; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 31, 0 -; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64-TRAP-NEXT: div.du $a0, $a0, $a1 +; LA64-TRAP-NEXT: addi.w $a1, $a1, 0 +; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 +; LA64-TRAP-NEXT: div.wu $a0, $a0, $a1 ; LA64-TRAP-NEXT: bnez $a1, .LBB11_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 @@ -444,9 +440,7 @@ define i32 @udiv_ui32_si32_si32(i32 signext %a, i32 signext %b) { ; ; LA64-LABEL: udiv_ui32_si32_si32: ; LA64: # %bb.0: # %entry -; LA64-NEXT: bstrpick.d $a1, $a1, 31, 0 -; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64-NEXT: div.du $a0, $a0, $a1 +; LA64-NEXT: div.wu $a0, $a0, $a1 ; LA64-NEXT: ret ; ; LA32-TRAP-LABEL: udiv_ui32_si32_si32: @@ -460,9 +454,7 @@ define i32 @udiv_ui32_si32_si32(i32 signext %a, i32 signext %b) { ; ; LA64-TRAP-LABEL: udiv_ui32_si32_si32: ; LA64-TRAP: # %bb.0: # %entry -; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 31, 0 -; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64-TRAP-NEXT: div.du $a0, $a0, $a1 +; LA64-TRAP-NEXT: div.wu $a0, $a0, $a1 ; LA64-TRAP-NEXT: bnez $a1, .LBB12_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 @@ -481,10 +473,9 @@ define signext i32 @udiv_si32_ui32_ui32(i32 %a, i32 %b) { ; ; LA64-LABEL: udiv_si32_ui32_ui32: ; LA64: # %bb.0: # %entry -; LA64-NEXT: bstrpick.d $a1, $a1, 31, 0 -; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64-NEXT: div.du $a0, $a0, $a1 +; LA64-NEXT: addi.w $a1, $a1, 0 ; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: div.wu $a0, $a0, $a1 ; LA64-NEXT: ret ; ; LA32-TRAP-LABEL: udiv_si32_ui32_ui32: @@ -498,14 +489,13 @@ define signext i32 @udiv_si32_ui32_ui32(i32 %a, i32 %b) { ; ; LA64-TRAP-LABEL: udiv_si32_ui32_ui32: ; LA64-TRAP: # %bb.0: # %entry -; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 31, 0 -; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64-TRAP-NEXT: div.du $a0, $a0, $a1 +; LA64-TRAP-NEXT: addi.w $a1, $a1, 0 +; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 +; LA64-TRAP-NEXT: div.wu $a0, $a0, $a1 ; LA64-TRAP-NEXT: bnez $a1, .LBB13_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 ; LA64-TRAP-NEXT: .LBB13_2: # %entry -; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 ; LA64-TRAP-NEXT: ret entry: %r = udiv i32 %a, %b @@ -520,10 +510,7 @@ define signext i32 @udiv_si32_si32_si32(i32 signext %a, i32 signext %b) { ; ; LA64-LABEL: udiv_si32_si32_si32: ; LA64: # %bb.0: # %entry -; LA64-NEXT: bstrpick.d $a1, $a1, 31, 0 -; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64-NEXT: div.du $a0, $a0, $a1 -; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: div.wu $a0, $a0, $a1 ; LA64-NEXT: ret ; ; LA32-TRAP-LABEL: udiv_si32_si32_si32: @@ -537,14 +524,11 @@ define signext i32 @udiv_si32_si32_si32(i32 signext %a, i32 signext %b) { ; ; LA64-TRAP-LABEL: udiv_si32_si32_si32: ; LA64-TRAP: # %bb.0: # %entry -; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 31, 0 -; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64-TRAP-NEXT: div.du $a0, $a0, $a1 +; LA64-TRAP-NEXT: div.wu $a0, $a0, $a1 ; LA64-TRAP-NEXT: bnez $a1, .LBB14_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 ; LA64-TRAP-NEXT: .LBB14_2: # %entry -; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 ; LA64-TRAP-NEXT: ret entry: %r = udiv i32 %a, %b @@ -995,9 +979,9 @@ define i32 @urem_i32(i32 %a, i32 %b) { ; ; LA64-LABEL: urem_i32: ; LA64: # %bb.0: # %entry -; LA64-NEXT: bstrpick.d $a1, $a1, 31, 0 -; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64-NEXT: mod.du $a0, $a0, $a1 +; LA64-NEXT: addi.w $a1, $a1, 0 +; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: mod.wu $a0, $a0, $a1 ; LA64-NEXT: ret ; ; LA32-TRAP-LABEL: urem_i32: @@ -1011,9 +995,9 @@ define i32 @urem_i32(i32 %a, i32 %b) { ; ; LA64-TRAP-LABEL: urem_i32: ; LA64-TRAP: # %bb.0: # %entry -; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 31, 0 -; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64-TRAP-NEXT: mod.du $a0, $a0, $a1 +; LA64-TRAP-NEXT: addi.w $a1, $a1, 0 +; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 +; LA64-TRAP-NEXT: mod.wu $a0, $a0, $a1 ; LA64-TRAP-NEXT: bnez $a1, .LBB27_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 @@ -1032,9 +1016,7 @@ define i32 @urem_ui32_si32_si32(i32 signext %a, i32 signext %b) { ; ; LA64-LABEL: urem_ui32_si32_si32: ; LA64: # %bb.0: # %entry -; LA64-NEXT: bstrpick.d $a1, $a1, 31, 0 -; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64-NEXT: mod.du $a0, $a0, $a1 +; LA64-NEXT: mod.wu $a0, $a0, $a1 ; LA64-NEXT: ret ; ; LA32-TRAP-LABEL: urem_ui32_si32_si32: @@ -1048,9 +1030,7 @@ define i32 @urem_ui32_si32_si32(i32 signext %a, i32 signext %b) { ; ; LA64-TRAP-LABEL: urem_ui32_si32_si32: ; LA64-TRAP: # %bb.0: # %entry -; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 31, 0 -; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64-TRAP-NEXT: mod.du $a0, $a0, $a1 +; LA64-TRAP-NEXT: mod.wu $a0, $a0, $a1 ; LA64-TRAP-NEXT: bnez $a1, .LBB28_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 @@ -1069,10 +1049,9 @@ define signext i32 @urem_si32_ui32_ui32(i32 %a, i32 %b) { ; ; LA64-LABEL: urem_si32_ui32_ui32: ; LA64: # %bb.0: # %entry -; LA64-NEXT: bstrpick.d $a1, $a1, 31, 0 -; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64-NEXT: mod.du $a0, $a0, $a1 +; LA64-NEXT: addi.w $a1, $a1, 0 ; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: mod.wu $a0, $a0, $a1 ; LA64-NEXT: ret ; ; LA32-TRAP-LABEL: urem_si32_ui32_ui32: @@ -1086,14 +1065,13 @@ define signext i32 @urem_si32_ui32_ui32(i32 %a, i32 %b) { ; ; LA64-TRAP-LABEL: urem_si32_ui32_ui32: ; LA64-TRAP: # %bb.0: # %entry -; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 31, 0 -; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64-TRAP-NEXT: mod.du $a0, $a0, $a1 +; LA64-TRAP-NEXT: addi.w $a1, $a1, 0 +; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 +; LA64-TRAP-NEXT: mod.wu $a0, $a0, $a1 ; LA64-TRAP-NEXT: bnez $a1, .LBB29_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 ; LA64-TRAP-NEXT: .LBB29_2: # %entry -; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 ; LA64-TRAP-NEXT: ret entry: %r = urem i32 %a, %b @@ -1108,10 +1086,7 @@ define signext i32 @urem_si32_si32_si32(i32 signext %a, i32 signext %b) { ; ; LA64-LABEL: urem_si32_si32_si32: ; LA64: # %bb.0: # %entry -; LA64-NEXT: bstrpick.d $a1, $a1, 31, 0 -; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64-NEXT: mod.du $a0, $a0, $a1 -; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: mod.wu $a0, $a0, $a1 ; LA64-NEXT: ret ; ; LA32-TRAP-LABEL: urem_si32_si32_si32: @@ -1125,14 +1100,11 @@ define signext i32 @urem_si32_si32_si32(i32 signext %a, i32 signext %b) { ; ; LA64-TRAP-LABEL: urem_si32_si32_si32: ; LA64-TRAP: # %bb.0: # %entry -; LA64-TRAP-NEXT: bstrpick.d $a1, $a1, 31, 0 -; LA64-TRAP-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64-TRAP-NEXT: mod.du $a0, $a0, $a1 +; LA64-TRAP-NEXT: mod.wu $a0, $a0, $a1 ; LA64-TRAP-NEXT: bnez $a1, .LBB30_2 ; LA64-TRAP-NEXT: # %bb.1: # %entry ; LA64-TRAP-NEXT: break 7 ; LA64-TRAP-NEXT: .LBB30_2: # %entry -; LA64-TRAP-NEXT: addi.w $a0, $a0, 0 ; LA64-TRAP-NEXT: ret entry: %r = urem i32 %a, %b -- GitLab From 6582efc263c0df921b88b03bbdcd28a89daaa641 Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Mon, 20 May 2024 09:36:45 +0200 Subject: [PATCH 064/793] [Clang] Fix __is_array returning true for zero-sized arrays (#86652) Fixes #54705 --- clang/docs/ReleaseNotes.rst | 3 +++ clang/lib/Sema/SemaExprCXX.cpp | 8 ++++++++ clang/test/SemaCXX/type-traits.cpp | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7af5869d2176..5a123b0b86dd 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -586,6 +586,9 @@ Bug Fixes in This Version - Clang now correctly disallows VLA type compound literals, e.g. ``(int[size]){}``, as the C standard mandates. (#GH89835) +- ``__is_array`` and ``__is_bounded_array`` no longer return ``true`` for + zero-sized arrays. Fixes (#GH54705). + Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index e4601f7d6c47..f543e006060d 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5217,10 +5217,18 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, case UTT_IsFloatingPoint: return T->isFloatingType(); case UTT_IsArray: + // Zero-sized arrays aren't considered arrays in partial specializations, + // so __is_array shouldn't consider them arrays either. + if (const auto *CAT = C.getAsConstantArrayType(T)) + return CAT->getSize() != 0; return T->isArrayType(); case UTT_IsBoundedArray: if (DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___is_bounded_array)) return false; + // Zero-sized arrays aren't considered arrays in partial specializations, + // so __is_bounded_array shouldn't consider them arrays either. + if (const auto *CAT = C.getAsConstantArrayType(T)) + return CAT->getSize() != 0; return T->isArrayType() && !T->isIncompleteArrayType(); case UTT_IsUnboundedArray: if (DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___is_unbounded_array)) diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp index f2fd45762abf..d40605f56f1e 100644 --- a/clang/test/SemaCXX/type-traits.cpp +++ b/clang/test/SemaCXX/type-traits.cpp @@ -25,6 +25,7 @@ typedef Empty EmptyArMB[1][2]; typedef int Int; typedef Int IntAr[10]; typedef Int IntArNB[]; +typedef Int IntArZero[0]; class Statics { static int priv; static NonPOD np; }; union EmptyUnion {}; union IncompleteUnion; // expected-note {{forward declaration of 'IncompleteUnion'}} @@ -685,6 +686,7 @@ void is_array() { static_assert(__is_array(IntAr)); static_assert(__is_array(IntArNB)); + static_assert(!__is_array(IntArZero)); static_assert(__is_array(UnionAr)); static_assert(!__is_array(void)); @@ -714,6 +716,7 @@ void is_array() void is_bounded_array(int n) { static_assert(__is_bounded_array(IntAr)); static_assert(!__is_bounded_array(IntArNB)); + static_assert(!__is_bounded_array(IntArZero)); static_assert(__is_bounded_array(UnionAr)); static_assert(!__is_bounded_array(void)); @@ -746,6 +749,7 @@ void is_bounded_array(int n) { void is_unbounded_array(int n) { static_assert(!__is_unbounded_array(IntAr)); static_assert(__is_unbounded_array(IntArNB)); + static_assert(!__is_unbounded_array(IntArZero)); static_assert(!__is_unbounded_array(UnionAr)); static_assert(!__is_unbounded_array(void)); -- GitLab From da6a0b7af29a222b2e16a10155b49d4fafe967f3 Mon Sep 17 00:00:00 2001 From: Sven van Haastregt Date: Mon, 20 May 2024 09:37:53 +0200 Subject: [PATCH 065/793] [OpenCL] Add cl_khr_kernel_clock builtins (#91950) --- clang/lib/Headers/opencl-c-base.h | 4 ++++ clang/lib/Headers/opencl-c.h | 15 +++++++++++++++ clang/lib/Sema/OpenCLBuiltins.td | 14 ++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/clang/lib/Headers/opencl-c-base.h b/clang/lib/Headers/opencl-c-base.h index 2494f6213fc5..786678b9d8a7 100644 --- a/clang/lib/Headers/opencl-c-base.h +++ b/clang/lib/Headers/opencl-c-base.h @@ -46,6 +46,10 @@ #define __opencl_c_ext_fp32_global_atomic_min_max 1 #define __opencl_c_ext_fp32_local_atomic_min_max 1 #define __opencl_c_ext_image_raw10_raw12 1 +#define cl_khr_kernel_clock 1 +#define __opencl_c_kernel_clock_scope_device 1 +#define __opencl_c_kernel_clock_scope_work_group 1 +#define __opencl_c_kernel_clock_scope_sub_group 1 #endif // defined(__SPIR__) || defined(__SPIRV__) #endif // (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200) diff --git a/clang/lib/Headers/opencl-c.h b/clang/lib/Headers/opencl-c.h index 288bb18bc654..20719b74b6b8 100644 --- a/clang/lib/Headers/opencl-c.h +++ b/clang/lib/Headers/opencl-c.h @@ -17314,6 +17314,21 @@ half __ovld __conv sub_group_clustered_rotate(half, int, uint); #endif // cl_khr_fp16 #endif // cl_khr_subgroup_rotate +#if defined(cl_khr_kernel_clock) +#if defined(__opencl_c_kernel_clock_scope_device) +ulong __ovld clock_read_device(); +uint2 __ovld clock_read_hilo_device(); +#endif // __opencl_c_kernel_clock_scope_device +#if defined(__opencl_c_kernel_clock_scope_work_group) +ulong __ovld clock_read_work_group(); +uint2 __ovld clock_read_hilo_work_group(); +#endif // __opencl_c_kernel_clock_scope_work_group +#if defined(__opencl_c_kernel_clock_scope_sub_group) +ulong __ovld clock_read_sub_group(); +uint2 __ovld clock_read_hilo_sub_group(); +#endif // __opencl_c_kernel_clock_scope_sub_group +#endif // cl_khr_kernel_clock + #if defined(cl_intel_subgroups) // Intel-Specific Sub Group Functions float __ovld __conv intel_sub_group_shuffle( float , uint ); diff --git a/clang/lib/Sema/OpenCLBuiltins.td b/clang/lib/Sema/OpenCLBuiltins.td index a7bdfe20b982..4da61429fcce 100644 --- a/clang/lib/Sema/OpenCLBuiltins.td +++ b/clang/lib/Sema/OpenCLBuiltins.td @@ -1852,6 +1852,20 @@ let Extension = FunctionExtension<"cl_khr_subgroup_rotate"> in { def : Builtin<"sub_group_clustered_rotate", [AGenType1, AGenType1, Int, UInt], Attr.Convergent>; } +// cl_khr_kernel_clock +let Extension = FunctionExtension<"cl_khr_kernel_clock __opencl_c_kernel_clock_scope_device"> in { + def : Builtin<"clock_read_device", [ULong]>; + def : Builtin<"clock_read_hilo_device", [VectorType]>; +} +let Extension = FunctionExtension<"cl_khr_kernel_clock __opencl_c_kernel_clock_scope_work_group"> in { + def : Builtin<"clock_read_work_group", [ULong]>; + def : Builtin<"clock_read_hilo_work_group", [VectorType]>; +} +let Extension = FunctionExtension<"cl_khr_kernel_clock __opencl_c_kernel_clock_scope_sub_group"> in { + def : Builtin<"clock_read_sub_group", [ULong]>; + def : Builtin<"clock_read_hilo_sub_group", [VectorType]>; +} + //-------------------------------------------------------------------- // Arm extensions. let Extension = ArmIntegerDotProductInt8 in { -- GitLab From 50b2bd4a25bb3a7a0790cb59e1240099efd7092e Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Mon, 20 May 2024 08:59:02 +0100 Subject: [PATCH 066/793] [clang][ExtractAPI] Remove symbols defined in categories to external types unless requested (#92522) rdar://128259890 --- .../Serialization/SymbolGraphSerializer.h | 9 +++++++-- .../Serialization/SymbolGraphSerializer.cpp | 11 +++++++++-- clang/test/ExtractAPI/objc_external_category.m | 18 +++++++++++++----- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h index 724b087f7aea..27e9167ca1ad 100644 --- a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h +++ b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h @@ -102,6 +102,8 @@ private: const bool EmitSymbolLabelsForTesting = false; + const bool SkipSymbolsInCategoriesToExternalTypes = false; + /// The object instantiated by the last call to serializeAPIRecord. Object *CurrentSymbol = nullptr; @@ -271,10 +273,13 @@ public: SymbolGraphSerializer(const APISet &API, const APIIgnoresList &IgnoresList, bool EmitSymbolLabelsForTesting = false, - bool ForceEmitToMainModule = false) + bool ForceEmitToMainModule = false, + bool SkipSymbolsInCategoriesToExternalTypes = false) : Base(API), ForceEmitToMainModule(ForceEmitToMainModule), IgnoresList(IgnoresList), - EmitSymbolLabelsForTesting(EmitSymbolLabelsForTesting) {} + EmitSymbolLabelsForTesting(EmitSymbolLabelsForTesting), + SkipSymbolsInCategoriesToExternalTypes( + SkipSymbolsInCategoriesToExternalTypes) {} }; } // namespace extractapi diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index c16d4623f115..08e711cafae2 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -925,6 +925,10 @@ bool SymbolGraphSerializer::visitObjCInterfaceRecord( bool SymbolGraphSerializer::traverseObjCCategoryRecord( const ObjCCategoryRecord *Record) { + if (SkipSymbolsInCategoriesToExternalTypes && + !API.findRecordForUSR(Record->Interface.USR)) + return true; + auto *CurrentModule = ModuleForCurrentSymbol; if (Record->isExtendingExternalModule()) ModuleForCurrentSymbol = &ExtendedModules[Record->Interface.Source]; @@ -1040,8 +1044,11 @@ void SymbolGraphSerializer::serializeGraphToStream( void SymbolGraphSerializer::serializeMainSymbolGraph( raw_ostream &OS, const APISet &API, const APIIgnoresList &IgnoresList, SymbolGraphSerializerOption Options) { - SymbolGraphSerializer Serializer(API, IgnoresList, - Options.EmitSymbolLabelsForTesting); + SymbolGraphSerializer Serializer( + API, IgnoresList, Options.EmitSymbolLabelsForTesting, + /*ForceEmitToMainModule=*/true, + /*SkipSymbolsInCategoriesToExternalTypes=*/true); + Serializer.traverseAPISet(); Serializer.serializeGraphToStream(OS, Options, API.ProductName, std::move(Serializer.MainModule)); diff --git a/clang/test/ExtractAPI/objc_external_category.m b/clang/test/ExtractAPI/objc_external_category.m index 47e699cb91c0..8afc92489f28 100644 --- a/clang/test/ExtractAPI/objc_external_category.m +++ b/clang/test/ExtractAPI/objc_external_category.m @@ -4,6 +4,9 @@ // RUN: --emit-extension-symbol-graphs --symbol-graph-dir=%t/symbols \ // RUN: --product-name=Module -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules-cache \ // RUN: -triple arm64-apple-macosx -x objective-c-header %t/input.h -verify +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: --product-name=Module -o %t/ModuleNoExt.symbols.json -triple arm64-apple-macosx \ +// RUN: -x objective-c-header %t/input.h //--- input.h #include "ExternalModule.h" @@ -28,15 +31,20 @@ module ExternalModule { header "ExternalModule.h" } +// Main symbol graph from the build with extension SGFs // RUN: FileCheck %s --input-file %t/symbols/Module.symbols.json --check-prefix MOD + // MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(py)Property $ c:objc(cs)ExtInterface" // MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(im)InstanceMethod $ c:objc(cs)ExtInterface" // MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(cm)ClassMethod $ c:objc(cs)ExtInterface" -// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface(py)Property" -// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface(im)InstanceMethod" -// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface(cm)ClassMethod" -// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface" -// MOD-DAG: "!testLabel": "c:objc(cs)ModInterface" +// MOD-NOT: "c:objc(cs)ExtInterface(py)Property" +// MOD-NOT: "c:objc(cs)ExtInterface(im)InstanceMethod" +// MOD-NOT: "c:objc(cs)ExtInterface(cm)ClassMethod" +// MOD-NOT: "c:objc(cs)ExtInterface" +// MOD-DAG: "c:objc(cs)ModInterface" + +// Symbol graph from the build without extension SGFs should be identical to main symbol graph with extension SGFs +// RUN: diff %t/symbols/Module.symbols.json %t/ModuleNoExt.symbols.json // RUN: FileCheck %s --input-file %t/symbols/ExternalModule@Module.symbols.json --check-prefix EXT // EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(py)Property $ c:objc(cs)ExtInterface" -- GitLab From b60e62896e2665e1a0ac51fc9942c1c4d31c0f53 Mon Sep 17 00:00:00 2001 From: Elvis Wang <110374989+ElvisWang123@users.noreply.github.com> Date: Mon, 20 May 2024 16:03:18 +0800 Subject: [PATCH 067/793] [RISCV][CostModel] Remove cost of icmp inst in icmp+select with SFB. (#91158) With ShortFowrardBranchOpt(SFB) or ConditionalMoveFusion, scalar ICmp and scalar Select instructions will lower to SELECT_CC and lower to PseudoCCMOVGPR which will generate a conditional branch instruction and a move instruction. The cost of scalar (ICmp + Select) = (0 + Select instruction cost) --- .../Target/RISCV/RISCVTargetTransformInfo.cpp | 17 ++ .../Analysis/CostModel/RISCV/cmp-select.ll | 258 ++++++++++++++++++ 2 files changed, 275 insertions(+) create mode 100644 llvm/test/Analysis/CostModel/RISCV/cmp-select.ll diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp index b73ed208ed74..ca8279672c09 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -14,9 +14,11 @@ #include "llvm/CodeGen/CostTable.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/PatternMatch.h" #include #include using namespace llvm; +using namespace llvm::PatternMatch; #define DEBUG_TYPE "riscvtti" @@ -1469,6 +1471,21 @@ InstructionCost RISCVTTIImpl::getCmpSelInstrCost(unsigned Opcode, Type *ValTy, } } + // With ShortForwardBranchOpt or ConditionalMoveFusion, scalar icmp + select + // instructions will lower to SELECT_CC and lower to PseudoCCMOVGPR which will + // generate a conditional branch + mv. The cost of scalar (icmp + select) will + // be (0 + select instr cost). + if (ST->hasConditionalMoveFusion() && I && isa(I) && + ValTy->isIntegerTy() && !I->user_empty()) { + if (all_of(I->users(), [&](const User *U) { + return match(U, m_Select(m_Specific(I), m_Value(), m_Value())) && + U->getType()->isIntegerTy() && + !isa(U->getOperand(1)) && + !isa(U->getOperand(2)); + })) + return 0; + } + // TODO: Add cost for scalar type. return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind, I); diff --git a/llvm/test/Analysis/CostModel/RISCV/cmp-select.ll b/llvm/test/Analysis/CostModel/RISCV/cmp-select.ll new file mode 100644 index 000000000000..dc0810b12869 --- /dev/null +++ b/llvm/test/Analysis/CostModel/RISCV/cmp-select.ll @@ -0,0 +1,258 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py +; RUN: opt < %s -mtriple=riscv64 -mattr=+v,+f,+short-forward-branch-opt -passes="print" -cost-kind=throughput 2>&1 -disable-output | FileCheck %s --check-prefixes=SFB64 +; RUN: opt < %s -mtriple=riscv64 -mattr=+v,+f -passes="print" -cost-kind=throughput 2>&1 -disable-output | FileCheck %s --check-prefixes=RV64 + +define i32 @icmp-iselect(i64 %ca, i64 %cb, i32 %a, i32 %b) { +; SFB64-LABEL: 'icmp-iselect' +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %cmp1 = icmp slt i64 %ca, %cb +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select i1 %cmp1, i32 %a, i32 %b +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %select1 +; +; RV64-LABEL: 'icmp-iselect' +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %cmp1 = icmp slt i64 %ca, %cb +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select i1 %cmp1, i32 %a, i32 %b +; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %select1 +; + %cmp1 = icmp slt i64 %ca, %cb + %select1 = select i1 %cmp1, i32 %a, i32 %b + ret i32 %select1 +} + +define i32 @icmp-iselects(i64 %ca, i64 %cb, i32 %a, i32 %b, i32 %c) { +; SFB64-LABEL: 'icmp-iselects' +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %cmp1 = icmp slt i64 %ca, %cb +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select i1 %cmp1, i32 %a, i32 %b +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select2 = select i1 %cmp1, i32 %a, i32 %c +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ret = add i32 %select1, %select2 +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %ret +; +; RV64-LABEL: 'icmp-iselects' +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %cmp1 = icmp slt i64 %ca, %cb +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select i1 %cmp1, i32 %a, i32 %b +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select2 = select i1 %cmp1, i32 %a, i32 %c +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ret = add i32 %select1, %select2 +; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %ret +; + %cmp1 = icmp slt i64 %ca, %cb + %select1 = select i1 %cmp1, i32 %a, i32 %b + %select2 = select i1 %cmp1, i32 %a, i32 %c + %ret = add i32 %select1, %select2 + ret i32 %ret +} + +define i32 @icmp-ifselects(i64 %ca, i64 %cb, i32 %a, i32 %b, float %c, float %d) { +; SFB64-LABEL: 'icmp-ifselects' +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %cmp1 = icmp slt i64 %ca, %cb +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select i1 %cmp1, i32 %a, i32 %b +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select2 = select i1 %cmp1, float %c, float %d +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %selectint = fptosi float %select2 to i32 +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ret = add i32 %select1, %selectint +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %ret +; +; RV64-LABEL: 'icmp-ifselects' +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %cmp1 = icmp slt i64 %ca, %cb +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select i1 %cmp1, i32 %a, i32 %b +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select2 = select i1 %cmp1, float %c, float %d +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %selectint = fptosi float %select2 to i32 +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ret = add i32 %select1, %selectint +; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %ret +; + %cmp1 = icmp slt i64 %ca, %cb + %select1 = select i1 %cmp1, i32 %a, i32 %b + %select2 = select i1 %cmp1, float %c, float %d + %selectint = fptosi float %select2 to i32 + %ret = add i32 %select1, %selectint + ret i32 %ret +} + +define i32 @constant-icmp-iselect(i64 %ca, i64 %cb, i32 %a) { +; SFB64-LABEL: 'constant-icmp-iselect' +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %cmp1 = icmp slt i64 %ca, %cb +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select i1 %cmp1, i32 %a, i32 7 +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %select1 +; +; RV64-LABEL: 'constant-icmp-iselect' +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %cmp1 = icmp slt i64 %ca, %cb +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select i1 %cmp1, i32 %a, i32 7 +; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %select1 +; + %cmp1 = icmp slt i64 %ca, %cb + %select1 = select i1 %cmp1, i32 %a, i32 7 + ret i32 %select1 +} + +define i32 @fcmp-iselect(float %ca, float %cb, i32 %a, i32 %b) { +; SFB64-LABEL: 'fcmp-iselect' +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %fcmp1 = fcmp ogt float %ca, %cb +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select i1 %fcmp1, i32 %a, i32 %b +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %select1 +; +; RV64-LABEL: 'fcmp-iselect' +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %fcmp1 = fcmp ogt float %ca, %cb +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select i1 %fcmp1, i32 %a, i32 %b +; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %select1 +; + %fcmp1 = fcmp ogt float %ca, %cb + %select1 = select i1 %fcmp1, i32 %a, i32 %b + ret i32 %select1 +} + +define float @fcmp-fselect(float %ca, float %cb, float %a, float %b) { +; SFB64-LABEL: 'fcmp-fselect' +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %fcmp1 = fcmp ogt float %ca, %cb +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %fselect1 = select i1 %fcmp1, float %a, float %b +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %fselect1 +; +; RV64-LABEL: 'fcmp-fselect' +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %fcmp1 = fcmp ogt float %ca, %cb +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %fselect1 = select i1 %fcmp1, float %a, float %b +; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %fselect1 +; + %fcmp1 = fcmp ogt float %ca, %cb + %fselect1 = select i1 %fcmp1, float %a, float %b + ret float %fselect1 +} + +define float @icmp-fselect(i64 %ca, i64 %cb, float %a, float %b) { +; SFB64-LABEL: 'icmp-fselect' +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %icmp1 = icmp slt i64 %ca, %cb +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %fselect1 = select i1 %icmp1, float %a, float %b +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %fselect1 +; +; RV64-LABEL: 'icmp-fselect' +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %icmp1 = icmp slt i64 %ca, %cb +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %fselect1 = select i1 %icmp1, float %a, float %b +; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %fselect1 +; + %icmp1 = icmp slt i64 %ca, %cb + %fselect1 = select i1 %icmp1, float %a, float %b + ret float %fselect1 +} + +define <2 x i32> @vector-icmp-vector-iselect(<2 x i32> %ca, <2 x i32> %cb, <2 x i32> %a, <2 x i32> %b) { +; SFB64-LABEL: 'vector-icmp-vector-iselect' +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %icmp = icmp slt <2 x i32> %ca, %cb +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select <2 x i1> %icmp, <2 x i32> %a, <2 x i32> %b +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x i32> %select1 +; +; RV64-LABEL: 'vector-icmp-vector-iselect' +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %icmp = icmp slt <2 x i32> %ca, %cb +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select <2 x i1> %icmp, <2 x i32> %a, <2 x i32> %b +; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x i32> %select1 +; + %icmp = icmp slt <2 x i32> %ca, %cb + %select1 = select <2 x i1> %icmp, <2 x i32> %a, <2 x i32> %b + ret <2 x i32> %select1 +} + +define <2 x i32> @vector-fcmp-vector-iselect(<2 x float> %ca, <2 x float> %cb, <2 x i32> %a, <2 x i32> %b) { +; SFB64-LABEL: 'vector-fcmp-vector-iselect' +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %fcmp1 = fcmp ogt <2 x float> %ca, %cb +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select <2 x i1> %fcmp1, <2 x i32> %a, <2 x i32> %b +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x i32> %select1 +; +; RV64-LABEL: 'vector-fcmp-vector-iselect' +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %fcmp1 = fcmp ogt <2 x float> %ca, %cb +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select <2 x i1> %fcmp1, <2 x i32> %a, <2 x i32> %b +; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x i32> %select1 +; + %fcmp1 = fcmp ogt <2 x float> %ca, %cb + %select1 = select <2 x i1> %fcmp1, <2 x i32> %a, <2 x i32> %b + ret <2 x i32> %select1 +} + +define <2 x float> @vector-fcmp-vector-fselect(<2 x float> %ca, <2 x float> %cb, <2 x float> %a, <2 x float> %b) { +; SFB64-LABEL: 'vector-fcmp-vector-fselect' +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %fcmp1 = fcmp ogt <2 x float> %ca, %cb +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select <2 x i1> %fcmp1, <2 x float> %a, <2 x float> %b +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x float> %select1 +; +; RV64-LABEL: 'vector-fcmp-vector-fselect' +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %fcmp1 = fcmp ogt <2 x float> %ca, %cb +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select <2 x i1> %fcmp1, <2 x float> %a, <2 x float> %b +; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x float> %select1 +; + %fcmp1 = fcmp ogt <2 x float> %ca, %cb + %select1 = select <2 x i1> %fcmp1, <2 x float> %a, <2 x float> %b + ret <2 x float> %select1 +} + +define <2 x float> @vector-icmp-vector-fselect(<2 x i32> %ca, <2 x i32> %cb, <2 x float> %a, <2 x float> %b) { +; SFB64-LABEL: 'vector-icmp-vector-fselect' +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %icmp1 = icmp slt <2 x i32> %ca, %cb +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select <2 x i1> %icmp1, <2 x float> %a, <2 x float> %b +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x float> %select1 +; +; RV64-LABEL: 'vector-icmp-vector-fselect' +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %icmp1 = icmp slt <2 x i32> %ca, %cb +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %select1 = select <2 x i1> %icmp1, <2 x float> %a, <2 x float> %b +; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x float> %select1 +; + %icmp1 = icmp slt <2 x i32> %ca, %cb + %select1 = select <2 x i1> %icmp1, <2 x float> %a, <2 x float> %b + ret <2 x float> %select1 +} + +define <2 x float> @icmp-vector-fselect(i1 %ca, i1 %cb, <2 x float> %a, <2 x float> %b) { +; SFB64-LABEL: 'icmp-vector-fselect' +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %icmp1 = icmp slt i1 %ca, %cb +; SFB64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %select1 = select i1 %icmp1, <2 x float> %a, <2 x float> %b +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x float> %select1 +; +; RV64-LABEL: 'icmp-vector-fselect' +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %icmp1 = icmp slt i1 %ca, %cb +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %select1 = select i1 %icmp1, <2 x float> %a, <2 x float> %b +; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x float> %select1 +; + %icmp1 = icmp slt i1 %ca, %cb + %select1 = select i1 %icmp1, <2 x float> %a, <2 x float> %b + ret <2 x float> %select1 +} + +define <2 x i32> @icmp-vector-iselect(i1 %ca, i1 %cb, <2 x i32> %a, <2 x i32> %b) { +; SFB64-LABEL: 'icmp-vector-iselect' +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %icmp1 = icmp slt i1 %ca, %cb +; SFB64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %select1 = select i1 %icmp1, <2 x i32> %a, <2 x i32> %b +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x i32> %select1 +; +; RV64-LABEL: 'icmp-vector-iselect' +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %icmp1 = icmp slt i1 %ca, %cb +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %select1 = select i1 %icmp1, <2 x i32> %a, <2 x i32> %b +; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x i32> %select1 +; + %icmp1 = icmp slt i1 %ca, %cb + %select1 = select i1 %icmp1, <2 x i32> %a, <2 x i32> %b + ret <2 x i32> %select1 +} + +define <2 x float> @fcmp-vector-fselect(float %ca, float %cb, <2 x float> %a, <2 x float> %b) { +; SFB64-LABEL: 'fcmp-vector-fselect' +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %fcmp1 = fcmp ogt float %ca, %cb +; SFB64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %select1 = select i1 %fcmp1, <2 x float> %a, <2 x float> %b +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x float> %select1 +; +; RV64-LABEL: 'fcmp-vector-fselect' +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %fcmp1 = fcmp ogt float %ca, %cb +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %select1 = select i1 %fcmp1, <2 x float> %a, <2 x float> %b +; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x float> %select1 +; + %fcmp1 = fcmp ogt float %ca, %cb + %select1 = select i1 %fcmp1, <2 x float> %a, <2 x float> %b + ret <2 x float> %select1 +} + +define <2 x i32> @fcmp-vector-iselect(float %ca, float %cb, <2 x i32> %a, <2 x i32> %b) { +; SFB64-LABEL: 'fcmp-vector-iselect' +; SFB64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %fcmp1 = fcmp ogt float %ca, %cb +; SFB64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %select1 = select i1 %fcmp1, <2 x i32> %a, <2 x i32> %b +; SFB64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x i32> %select1 +; +; RV64-LABEL: 'fcmp-vector-iselect' +; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %fcmp1 = fcmp ogt float %ca, %cb +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %select1 = select i1 %fcmp1, <2 x i32> %a, <2 x i32> %b +; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x i32> %select1 +; + %fcmp1 = fcmp ogt float %ca, %cb + %select1 = select i1 %fcmp1, <2 x i32> %a, <2 x i32> %b + ret <2 x i32> %select1 +} -- GitLab From f5211d79b9edf56c08143491ccde38d480b40ab8 Mon Sep 17 00:00:00 2001 From: Shan Huang <52285902006@stu.ecnu.edu.cn> Date: Mon, 20 May 2024 16:39:48 +0800 Subject: [PATCH 068/793] [DebugInfo][GVNSink] Fix #77415: GVNSink fails to optimize LLVM IR with debug info (#77602) This PR fixes issue #77415 and is revised from PR #77419 . PR #77419 breaks the newly added test in the same PR on windows, because GVNSink is non-deterministic when sorting `BasicBlock*` pointers. This is reflected in the failure report. ``` # | C:\src\llvm-project\llvm\test\Transforms\GVNSink\sink-ignore-dbg-intrinsics.ll:28:10: error: CHECK: expected string not found in input # | ; CHECK: %a.sink = phi i32 [ %a, %if.then ], [ %b, %if.else ] # | ^ # | :24:8: note: scanning from here # | if.end: ; preds = %if.else, %if.then # | ^ # | :25:2: note: possible intended match here # | %b.sink = phi i32 [ %b, %if.else ], [ %a, %if.then ] # | ^ # | # | Input file: # | Check file: C:\src\llvm-project\llvm\test\Transforms\GVNSink\sink-ignore-dbg-intrinsics.ll ``` According to the report, what the CheckFile wants to match is the `%a.sink`, however there is `%b.sink`. But this mismatch does not mean that this commit is wrong, since the occurrence of either `%a.sink` or `%b.sink` is correct. The root cause of this test failure is the strict check rule in the regression test committed. So I refined the regression test with a more general check rule to only detect whether there is an instruction with suffix `.sink` in the `if.end` block. Hope this won't fail the test. If this PR still fails to build, I will close this PR and try to find another right way to fix this. --- llvm/lib/Transforms/Scalar/GVNSink.cpp | 6 +- .../GVNSink/sink-ignore-dbg-intrinsics.ll | 89 +++++++++++++++++++ 2 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 llvm/test/Transforms/GVNSink/sink-ignore-dbg-intrinsics.ll diff --git a/llvm/lib/Transforms/Scalar/GVNSink.cpp b/llvm/lib/Transforms/Scalar/GVNSink.cpp index 7a183e4d3aa8..b0f716cb1759 100644 --- a/llvm/lib/Transforms/Scalar/GVNSink.cpp +++ b/llvm/lib/Transforms/Scalar/GVNSink.cpp @@ -132,7 +132,7 @@ public: ActiveBlocks.remove(BB); continue; } - Insts.push_back(BB->getTerminator()->getPrevNode()); + Insts.push_back(BB->getTerminator()->getPrevNonDebugInstruction()); } if (Insts.empty()) Fail = true; @@ -168,7 +168,7 @@ public: if (Inst == &Inst->getParent()->front()) ActiveBlocks.remove(Inst->getParent()); else - NewInsts.push_back(Inst->getPrevNode()); + NewInsts.push_back(Inst->getPrevNonDebugInstruction()); } if (NewInsts.empty()) { Fail = true; @@ -883,7 +883,7 @@ void GVNSink::sinkLastInstruction(ArrayRef Blocks, BasicBlock *BBEnd) { SmallVector Insts; for (BasicBlock *BB : Blocks) - Insts.push_back(BB->getTerminator()->getPrevNode()); + Insts.push_back(BB->getTerminator()->getPrevNonDebugInstruction()); Instruction *I0 = Insts.front(); SmallVector NewOperands; diff --git a/llvm/test/Transforms/GVNSink/sink-ignore-dbg-intrinsics.ll b/llvm/test/Transforms/GVNSink/sink-ignore-dbg-intrinsics.ll new file mode 100644 index 000000000000..8aafd689e781 --- /dev/null +++ b/llvm/test/Transforms/GVNSink/sink-ignore-dbg-intrinsics.ll @@ -0,0 +1,89 @@ +; RUN: opt < %s -passes=gvn-sink -S | FileCheck %s + +; Test that GVNSink correctly performs the sink optimization in the presence of debug information + +; Function Attrs: noinline nounwind uwtable +define dso_local i32 @fun(i32 noundef %a, i32 noundef %b) #0 !dbg !10 { +; CHECK-LABEL: define dso_local i32 @fun( +; CHECK-SAME: i32 noundef [[A:%.*]], i32 noundef [[B:%.*]]) +; CHECK: if.end: +; CHECK: [[B_SINK:%.*]] = phi i32 [ [[B]], %if.else ], [ [[A]], %if.then ] +; CHECK: [[ADD1:%.*]] = add nsw i32 [[B_SINK]], 1 +; CHECK: [[XOR2:%.*]] = xor i32 [[ADD1]], 1 +; +entry: + tail call void @llvm.dbg.value(metadata i32 %a, metadata !15, metadata !DIExpression()), !dbg !16 + tail call void @llvm.dbg.value(metadata i32 %b, metadata !17, metadata !DIExpression()), !dbg !16 + %cmp = icmp sgt i32 %b, 10, !dbg !18 + br i1 %cmp, label %if.then, label %if.else, !dbg !20 + +if.then: ; preds = %entry + %add = add nsw i32 %a, 1, !dbg !21 + tail call void @llvm.dbg.value(metadata i32 %add, metadata !23, metadata !DIExpression()), !dbg !24 + %xor = xor i32 %add, 1, !dbg !25 + tail call void @llvm.dbg.value(metadata i32 %xor, metadata !26, metadata !DIExpression()), !dbg !24 + tail call void @llvm.dbg.value(metadata i32 %xor, metadata !27, metadata !DIExpression()), !dbg !16 + br label %if.end, !dbg !28 + +if.else: ; preds = %entry + %add1 = add nsw i32 %b, 1, !dbg !29 + tail call void @llvm.dbg.value(metadata i32 %add1, metadata !31, metadata !DIExpression()), !dbg !32 + %xor2 = xor i32 %add1, 1, !dbg !33 + tail call void @llvm.dbg.value(metadata i32 %xor2, metadata !34, metadata !DIExpression()), !dbg !32 + tail call void @llvm.dbg.value(metadata i32 %xor2, metadata !27, metadata !DIExpression()), !dbg !16 + br label %if.end + +if.end: ; preds = %if.else, %if.then + %ret.0 = phi i32 [ %xor, %if.then ], [ %xor2, %if.else ], !dbg !35 + tail call void @llvm.dbg.value(metadata i32 %ret.0, metadata !27, metadata !DIExpression()), !dbg !16 + ret i32 %ret.0, !dbg !36 +} + +; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { noinline nounwind uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 18.0.0git (https://github.com/llvm/llvm-project.git 5dfcb3e5d1d16bb4f8fce52b3c089119ed977e7f)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "main.c", directory: "/") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"PIE Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{i32 7, !"frame-pointer", i32 2} +!10 = distinct !DISubprogram(name: "fun", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14) +!11 = !DISubroutineType(types: !12) +!12 = !{!13, !13, !13} +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!14 = !{} +!15 = !DILocalVariable(name: "a", arg: 1, scope: !10, file: !1, line: 1, type: !13) +!16 = !DILocation(line: 0, scope: !10) +!17 = !DILocalVariable(name: "b", arg: 2, scope: !10, file: !1, line: 1, type: !13) +!18 = !DILocation(line: 3, column: 11, scope: !19) +!19 = distinct !DILexicalBlock(scope: !10, file: !1, line: 3, column: 9) +!20 = !DILocation(line: 3, column: 9, scope: !10) +!21 = !DILocation(line: 4, column: 20, scope: !22) +!22 = distinct !DILexicalBlock(scope: !19, file: !1, line: 3, column: 17) +!23 = !DILocalVariable(name: "a1", scope: !22, file: !1, line: 4, type: !13) +!24 = !DILocation(line: 0, scope: !22) +!25 = !DILocation(line: 5, column: 21, scope: !22) +!26 = !DILocalVariable(name: "a2", scope: !22, file: !1, line: 5, type: !13) +!27 = !DILocalVariable(name: "ret", scope: !10, file: !1, line: 2, type: !13) +!28 = !DILocation(line: 7, column: 5, scope: !22) +!29 = !DILocation(line: 8, column: 20, scope: !30) +!30 = distinct !DILexicalBlock(scope: !19, file: !1, line: 7, column: 12) +!31 = !DILocalVariable(name: "b1", scope: !30, file: !1, line: 8, type: !13) +!32 = !DILocation(line: 0, scope: !30) +!33 = !DILocation(line: 9, column: 21, scope: !30) +!34 = !DILocalVariable(name: "b2", scope: !30, file: !1, line: 9, type: !13) +!35 = !DILocation(line: 0, scope: !19) +!36 = !DILocation(line: 12, column: 5, scope: !10) -- GitLab From d3d6565c2453be2f580ff12b32cc5d0cb5c6c9d8 Mon Sep 17 00:00:00 2001 From: hanbeom Date: Mon, 20 May 2024 09:41:51 +0100 Subject: [PATCH 069/793] [AArch64] Add PreTest for optimizing `MOV` to `ORR` --- .../CodeGen/AArch64/movimm-expand-ldst.ll | 97 +++++++++++++++++++ .../CodeGen/AArch64/movimm-expand-ldst.mir | 35 +++++++ 2 files changed, 132 insertions(+) create mode 100644 llvm/test/CodeGen/AArch64/movimm-expand-ldst.ll create mode 100644 llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir diff --git a/llvm/test/CodeGen/AArch64/movimm-expand-ldst.ll b/llvm/test/CodeGen/AArch64/movimm-expand-ldst.ll new file mode 100644 index 000000000000..82bba7b5f854 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/movimm-expand-ldst.ll @@ -0,0 +1,97 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=aarch64 %s -o - | FileCheck %s + +define i64 @test0x1234567812345678() { +; CHECK-LABEL: test0x1234567812345678: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #22136 // =0x5678 +; CHECK-NEXT: movk x0, #4660, lsl #16 +; CHECK-NEXT: movk x0, #22136, lsl #32 +; CHECK-NEXT: movk x0, #4660, lsl #48 +; CHECK-NEXT: ret + ret i64 u0x1234567812345678 +} + +define i64 @test0xff3456ffff3456ff() { +; CHECK-LABEL: test0xff3456ffff3456ff: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #22271 // =0x56ff +; CHECK-NEXT: movk x0, #65332, lsl #16 +; CHECK-NEXT: movk x0, #22271, lsl #32 +; CHECK-NEXT: movk x0, #65332, lsl #48 +; CHECK-NEXT: ret + ret i64 u0xff3456ffff3456ff +} + +define i64 @test0x00345600345600() { +; CHECK-LABEL: test0x00345600345600: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #22016 // =0x5600 +; CHECK-NEXT: movk x0, #52, lsl #16 +; CHECK-NEXT: movk x0, #13398, lsl #32 +; CHECK-NEXT: ret + ret i64 u0x00345600345600 +} + +define i64 @test0x5555555555555555() { +; CHECK-LABEL: test0x5555555555555555: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #6148914691236517205 // =0x5555555555555555 +; CHECK-NEXT: ret + ret i64 u0x5555555555555555 +} + +define i64 @test0x5055555550555555() { +; CHECK-LABEL: test0x5055555550555555: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #6148914691236517205 // =0x5555555555555555 +; CHECK-NEXT: and x0, x0, #0xf0fffffff0ffffff +; CHECK-NEXT: ret + ret i64 u0x5055555550555555 +} + +define i64 @test0x0000555555555555() { +; CHECK-LABEL: test0x0000555555555555: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #6148914691236517205 // =0x5555555555555555 +; CHECK-NEXT: movk x0, #0, lsl #48 +; CHECK-NEXT: ret + ret i64 u0x0000555555555555 +} + +define i64 @test0x0000555500005555() { +; CHECK-LABEL: test0x0000555500005555: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #21845 // =0x5555 +; CHECK-NEXT: movk x0, #21845, lsl #32 +; CHECK-NEXT: ret + ret i64 u0x0000555500005555 +} + +define i64 @testu0xffff5555ffff5555() { +; CHECK-LABEL: testu0xffff5555ffff5555: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #-43691 // =0xffffffffffff5555 +; CHECK-NEXT: movk x0, #21845, lsl #32 +; CHECK-NEXT: ret + ret i64 u0xffff5555ffff5555 +} + +define i64 @testuu0xfffff555f555f555() { +; CHECK-LABEL: testuu0xfffff555f555f555: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #-2731 // =0xfffffffffffff555 +; CHECK-NEXT: movk x0, #62805, lsl #16 +; CHECK-NEXT: movk x0, #62805, lsl #32 +; CHECK-NEXT: ret + ret i64 u0xfffff555f555f555 +} + +define i64 @testuu0xf555f555f555f555() { +; CHECK-LABEL: testuu0xf555f555f555f555: +; CHECK: // %bb.0: +; CHECK-NEXT: mov x0, #6148914691236517205 // =0x5555555555555555 +; CHECK-NEXT: orr x0, x0, #0xe001e001e001e001 +; CHECK-NEXT: ret + ret i64 u0xf555f555f555f555 +} diff --git a/llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir b/llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir new file mode 100644 index 000000000000..de14437108c9 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir @@ -0,0 +1,35 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 +# RUN: llc -mtriple=aarch64 -verify-machineinstrs -run-pass=aarch64-expand-pseudo -run-pass=aarch64-ldst-opt -debug-only=aarch64-ldst-opt %s -o - | FileCheck %s +--- +name: test_fold_repeating_constant_load +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0 + ; CHECK-LABEL: name: test_fold_repeating_constant_load + ; CHECK: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x0 = MOVZXi 49370, 0 + ; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 320, 16 + ; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 49370, 32 + ; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 320, 48 + ; CHECK-NEXT: RET undef $lr, implicit $x0 + renamable $x0 = MOVi64imm 90284035103834330 + RET_ReallyLR implicit $x0 +... +--- +name: test_fold_repeating_constant_load_neg +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0 + ; CHECK-LABEL: name: test_fold_repeating_constant_load_neg + ; CHECK: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x0 = MOVZXi 320, 0 + ; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 49370, 16 + ; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 320, 32 + ; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 49370, 48 + ; CHECK-NEXT: RET undef $lr, implicit $x0 + renamable $x0 = MOVi64imm -4550323095879417536 + RET_ReallyLR implicit $x0 -- GitLab From 384bf545a1a7d8dfd16afd20ef07eb845495bac4 Mon Sep 17 00:00:00 2001 From: bd1976bris Date: Mon, 20 May 2024 09:48:35 +0100 Subject: [PATCH 070/793] [Driver][PS5] Set visibility option defaults (#92091) Adjust the PS5 driver defaults for the -fvisibility-from-dllstorageclass sub-options so that only globals with dllimport/dllexport annotations are adjusted. This allows globals without dllimport/export to retain the visibility and pre-emptability assigned during IR-Gen. Set -fvisibility=hidden on PS5 by default to compensate for no longer overriding the visibility of definitions without dllexport. Note there is no behavior change for PS4 (the behavior of overriding the visibility for all globals is retained on PS4). --- clang/lib/Driver/ToolChains/PS4CPU.cpp | 18 ++++++++- .../ps4-ps5-visibility-dllstorageclass.c | 39 ++++++++++++------- clang/test/Driver/ps4-visibility.cl | 32 +++++++++++++++ clang/test/Driver/ps5-visibility.cl | 33 ++++++++++++++++ 4 files changed, 107 insertions(+), 15 deletions(-) create mode 100644 clang/test/Driver/ps4-visibility.cl create mode 100644 clang/test/Driver/ps5-visibility.cl diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp index 7bf9aa79384c..3fd62d979309 100644 --- a/clang/lib/Driver/ToolChains/PS4CPU.cpp +++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp @@ -358,6 +358,12 @@ void toolchains::PS4PS5Base::addClangTargetOptions( CC1Args.push_back("-fno-use-init-array"); + // Default to `hidden` visibility for PS5. + if (getTriple().isPS5() && + !DriverArgs.hasArg(options::OPT_fvisibility_EQ, + options::OPT_fvisibility_ms_compat)) + CC1Args.push_back("-fvisibility=hidden"); + // Default to -fvisibility-global-new-delete=source for PS5. if (getTriple().isPS5() && !DriverArgs.hasArg(options::OPT_fvisibility_global_new_delete_EQ, @@ -376,11 +382,15 @@ void toolchains::PS4PS5Base::addClangTargetOptions( else CC1Args.push_back("-fvisibility-dllexport=protected"); + // For PS4 we override the visibilty of globals definitions without + // dllimport or dllexport annotations. if (DriverArgs.hasArg(options::OPT_fvisibility_nodllstorageclass_EQ)) DriverArgs.AddLastArg(CC1Args, options::OPT_fvisibility_nodllstorageclass_EQ); - else + else if (getTriple().isPS4()) CC1Args.push_back("-fvisibility-nodllstorageclass=hidden"); + else + CC1Args.push_back("-fvisibility-nodllstorageclass=keep"); if (DriverArgs.hasArg(options::OPT_fvisibility_externs_dllimport_EQ)) DriverArgs.AddLastArg(CC1Args, @@ -388,12 +398,16 @@ void toolchains::PS4PS5Base::addClangTargetOptions( else CC1Args.push_back("-fvisibility-externs-dllimport=default"); + // For PS4 we override the visibilty of external globals without + // dllimport or dllexport annotations. if (DriverArgs.hasArg( options::OPT_fvisibility_externs_nodllstorageclass_EQ)) DriverArgs.AddLastArg( CC1Args, options::OPT_fvisibility_externs_nodllstorageclass_EQ); - else + else if (getTriple().isPS4()) CC1Args.push_back("-fvisibility-externs-nodllstorageclass=default"); + else + CC1Args.push_back("-fvisibility-externs-nodllstorageclass=keep"); } } diff --git a/clang/test/Driver/ps4-ps5-visibility-dllstorageclass.c b/clang/test/Driver/ps4-ps5-visibility-dllstorageclass.c index 430827805a8f..71f8661679eb 100644 --- a/clang/test/Driver/ps4-ps5-visibility-dllstorageclass.c +++ b/clang/test/Driver/ps4-ps5-visibility-dllstorageclass.c @@ -1,16 +1,19 @@ // Check behaviour of -fvisibility-from-dllstorageclass options for PS4/PS5. // DEFINE: %{triple} = +// DEFINE: %{prefix} = // DEFINE: %{run} = \ // DEFINE: %clang -### -target %{triple} %s -Werror -o - 2>&1 | \ -// DEFINE: FileCheck %s --check-prefix=DEFAULTS \ +// DEFINE: FileCheck %s --check-prefixes=DEFAULTS,%{prefix} \ // DEFINE: --implicit-check-not=-fvisibility-from-dllstorageclass \ // DEFINE: --implicit-check-not=-fvisibility-dllexport \ // DEFINE: --implicit-check-not=-fvisibility-nodllstorageclass \ // DEFINE: --implicit-check-not=-fvisibility-externs-dllimport \ // DEFINE: --implicit-check-not=-fvisibility-externs-nodllstorageclass +// REDEFINE: %{prefix} = DEFAULTS-PS4 // REDEFINE: %{triple} = x86_64-scei-ps4 // RUN: %{run} +// REDEFINE: %{prefix} = DEFAULTS-PS5 // REDEFINE: %{triple} = x86_64-sie-ps5 // RUN: %{run} // @@ -20,25 +23,29 @@ // REDEFINE: -fvisibility-from-dllstorageclass \ // REDEFINE: -Werror \ // REDEFINE: %s -o - 2>&1 | \ -// REDEFINE: FileCheck %s --check-prefix=DEFAULTS \ +// REDEFINE: FileCheck %s --check-prefixes=DEFAULTS,%{prefix} \ // REDEFINE: --implicit-check-not=-fvisibility-from-dllstorageclass \ // REDEFINE: --implicit-check-not=-fvisibility-dllexport \ // REDEFINE: --implicit-check-not=-fvisibility-nodllstorageclass \ // REDEFINE: --implicit-check-not=-fvisibility-externs-dllimport \ // REDEFINE: --implicit-check-not=-fvisibility-externs-nodllstorageclass +// REDEFINE: %{prefix} = DEFAULTS-PS4 // REDEFINE: %{triple} = x86_64-scei-ps4 // RUN: %{run} +// REDEFINE: %{prefix} = DEFAULTS-PS5 // REDEFINE: %{triple} = x86_64-sie-ps5 // RUN: %{run} // DEFAULTS: "-fvisibility-from-dllstorageclass" // DEFAULTS-SAME: "-fvisibility-dllexport=protected" -// DEFAULTS-SAME: "-fvisibility-nodllstorageclass=hidden" +// DEFAULTS-PS4-SAME: "-fvisibility-nodllstorageclass=hidden" +// DEFAULTS-PS5-SAME: "-fvisibility-nodllstorageclass=keep" // DEFAULTS-SAME: "-fvisibility-externs-dllimport=default" -// DEFAULTS-SAME: "-fvisibility-externs-nodllstorageclass=default" +// DEFAULTS-PS4-SAME: "-fvisibility-externs-nodllstorageclass=default" +// DEFAULTS-PS5-SAME: "-fvisibility-externs-nodllstorageclass=keep" // REDEFINE: %{run} = \ -// REDEFINE: %clang -### -target x86_64-scei-ps4 \ +// REDEFINE: %clang -### -target %{triple} \ // REDEFINE: -fvisibility-from-dllstorageclass \ // REDEFINE: -fvisibility-dllexport=hidden \ // REDEFINE: -fvisibility-nodllstorageclass=protected \ @@ -64,37 +71,41 @@ // UNUSED-NEXT: warning: argument unused during compilation: '-fvisibility-externs-nodllstorageclass=protected' // REDEFINE: %{run} = \ -// REDEFINE: %clang -### -target x86_64-scei-ps4 \ +// REDEFINE: %clang -### -target %{triple} \ // REDEFINE: -fvisibility-nodllstorageclass=protected \ // REDEFINE: -fvisibility-externs-dllimport=hidden \ // REDEFINE: -Werror \ // REDEFINE: %s -o - 2>&1 | \ -// REDEFINE: FileCheck %s -check-prefix=SOME \ +// REDEFINE: FileCheck %s -check-prefixes=SOME,%{prefix} \ // REDEFINE: --implicit-check-not=-fvisibility-from-dllstorageclass \ // REDEFINE: --implicit-check-not=-fvisibility-dllexport \ // REDEFINE: --implicit-check-not=-fvisibility-nodllstorageclass \ // REDEFINE: --implicit-check-not=-fvisibility-externs-dllimport \ // REDEFINE: --implicit-check-not=-fvisibility-externs-nodllstorageclass +// REDEFINE: %{prefix} = SOME-PS4 // REDEFINE: %{triple} = x86_64-scei-ps4 // RUN: %{run} +// REDEFINE: %{prefix} = SOME-PS5 // REDEFINE: %{triple} = x86_64-sie-ps5 // RUN: %{run} // REDEFINE: %{run} = \ -// REDEFINE: %clang -### -target x86_64-scei-ps4 \ +// REDEFINE: %clang -### -target %{triple} \ // REDEFINE: -fvisibility-from-dllstorageclass \ // REDEFINE: -fvisibility-nodllstorageclass=protected \ // REDEFINE: -fvisibility-externs-dllimport=hidden \ // REDEFINE: -Werror \ // REDEFINE: %s -o - 2>&1 | \ -// REDEFINE: FileCheck %s -check-prefix=SOME \ +// REDEFINE: FileCheck %s -check-prefixes=SOME,%{prefix} \ // REDEFINE: --implicit-check-not=-fvisibility-from-dllstorageclass \ // REDEFINE: --implicit-check-not=-fvisibility-dllexport \ // REDEFINE: --implicit-check-not=-fvisibility-nodllstorageclass \ // REDEFINE: --implicit-check-not=-fvisibility-externs-dllimport \ // REDEFINE: --implicit-check-not=-fvisibility-externs-nodllstorageclass +// REDEFINE: %{prefix} = SOME-PS4 // REDEFINE: %{triple} = x86_64-scei-ps4 // RUN: %{run} +// REDEFINE: %{prefix} = SOME-PS5 // REDEFINE: %{triple} = x86_64-sie-ps5 // RUN: %{run} @@ -102,10 +113,11 @@ // SOME-SAME: "-fvisibility-dllexport=protected" // SOME-SAME: "-fvisibility-nodllstorageclass=protected" // SOME-SAME: "-fvisibility-externs-dllimport=hidden" -// SOME-SAME: "-fvisibility-externs-nodllstorageclass=default" +// SOME-PS4-SAME: "-fvisibility-externs-nodllstorageclass=default" +// SOME-PS5-SAME: "-fvisibility-externs-nodllstorageclass=keep" // REDEFINE: %{run} = \ -// REDEFINE: %clang -### -target x86_64-scei-ps4 \ +// REDEFINE: %clang -### -target %{triple} \ // REDEFINE: -fvisibility-dllexport=default \ // REDEFINE: -fvisibility-dllexport=hidden \ // REDEFINE: -fvisibility-nodllstorageclass=default \ @@ -121,14 +133,15 @@ // REDEFINE: --implicit-check-not=-fvisibility-dllexport \ // REDEFINE: --implicit-check-not=-fvisibility-nodllstorageclass \ // REDEFINE: --implicit-check-not=-fvisibility-externs-dllimport \ -// REDEFINE: --implicit-check-not=-fvisibility-externs-nodllstorageclass +// REDEFINE: --implicit-check-not=-fvisibility-externs-nodllstorageclass \ +// REDEFINE: --implicit-check-not="warning: argument unused" // REDEFINE: %{triple} = x86_64-scei-ps4 // RUN: %{run} // REDEFINE: %{triple} = x86_64-sie-ps5 // RUN: %{run} // REDEFINE: %{run} = \ -// REDEFINE: %clang -### -target x86_64-scei-ps4 \ +// REDEFINE: %clang -### -target %{triple} \ // REDEFINE: -fvisibility-from-dllstorageclass \ // REDEFINE: -fvisibility-dllexport=default \ // REDEFINE: -fvisibility-dllexport=hidden \ diff --git a/clang/test/Driver/ps4-visibility.cl b/clang/test/Driver/ps4-visibility.cl new file mode 100644 index 000000000000..a0ed7c71f1f0 --- /dev/null +++ b/clang/test/Driver/ps4-visibility.cl @@ -0,0 +1,32 @@ +/// Check PS4 specific interactions between visibility options. +/// Detailed testing of -fvisibility-from-dllstorageclass is covered elsewhere. + +/// Check defaults. +// RUN: %clang -### -target x86_64-scei-ps4 -x cl -c -emit-llvm %s 2>&1 | \ +// RUN: FileCheck -check-prefix=DEFAULT %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass +// DEFAULT-DAG: "-fvisibility-from-dllstorageclass" +// DEFAULT-DAG: "-fvisibility-dllexport=protected" +// DEFAULT-DAG: "-fvisibility-nodllstorageclass=hidden" +// DEFAULT-DAG: "-fvisibility-externs-dllimport=default" +// DEFAULT-DAG: "-fvisibility-externs-nodllstorageclass=default" + +/// Check that -fvisibility-from-dllstorageclass is added in the presence of -fvisibility=. +// RUN: %clang -### -target x86_64-scei-ps4 -x cl -c -emit-llvm -fvisibility=default %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=DEFAULT,VISEQUALS %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass +// VISEQUALS-DAG: "-fvisibility=default" + +/// Check that -fvisibility-from-dllstorageclass is added in the presence of -fvisibility-ms-compat. +// RUN: %clang -### -target x86_64-scei-ps4 -x cl -c -emit-llvm -fvisibility-ms-compat %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=DEFAULT,MSCOMPT %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass +// MSCOMPT-DAG: "-fvisibility=hidden" +// MSCOMPT-DAG: "-ftype-visibility=default" + +/// -fvisibility-from-dllstorageclass added explicitly. +// RUN: %clang -### -target x86_64-scei-ps4 -x cl -c -emit-llvm -fvisibility-from-dllstorageclass %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=DEFAULT %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass + +/// -fvisibility-from-dllstorageclass disabled explicitly. +// RUN: %clang -### -target x86_64-scei-ps4 -x cl -c -emit-llvm -fno-visibility-from-dllstorageclass %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=NOVISFROM %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass +// NOVISFROM-NOT: "-fvisibility-from-dllstorageclass" + diff --git a/clang/test/Driver/ps5-visibility.cl b/clang/test/Driver/ps5-visibility.cl new file mode 100644 index 000000000000..ad144057be63 --- /dev/null +++ b/clang/test/Driver/ps5-visibility.cl @@ -0,0 +1,33 @@ +/// Check PS5 specific interactions between visibility options. +/// Detailed testing of -fvisibility-from-dllstorageclass is covered elsewhere. + +/// Check defaults. +// RUN: %clang -### -target x86_64-sie-ps5 -x cl -c -emit-llvm %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=VDEFAULT,VGND_DEFAULT,DEFAULT %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass +// VDEFAULT-DAG: "-fvisibility=hidden" +// VGND_DEFAULT-DAG: "-fvisibility-global-new-delete=source" +// DEFAULT-DAG: "-fvisibility-from-dllstorageclass" +// DEFAULT-DAG: "-fvisibility-dllexport=protected" +// DEFAULT-DAG: "-fvisibility-nodllstorageclass=keep" +// DEFAULT-DAG: "-fvisibility-externs-dllimport=default" +// DEFAULT-DAG: "-fvisibility-externs-nodllstorageclass=keep" + +/// -fvisibility= specified explicitly. +// RUN: %clang -### -target x86_64-sie-ps5 -x cl -c -emit-llvm -fvisibility=protected %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=VPROTECTED,VGND_DEFAULT,DEFAULT %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass +// VPROTECTED-DAG: "-fvisibility=protected" + +/// -fvisibility-ms-compat added explicitly. +// RUN: %clang -### -target x86_64-sie-ps5 -x cl -c -emit-llvm -fvisibility-ms-compat %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=MSCOMPT,VGND_DEFAULT,DEFAULT %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass +// MSCOMPT-DAG: "-fvisibility=hidden" +// MSCOMPT-DAG: "-ftype-visibility=default" + +/// -fvisibility-from-dllstorageclass added explicitly. +// RUN: %clang -### -target x86_64-sie-ps5 -x cl -c -emit-llvm -fvisibility-from-dllstorageclass %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=VDEFAULT,VGND_DEFAULT,DEFAULT %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass + +/// -fvisibility-from-dllstorageclass disabled explicitly. +// RUN: %clang -### -target x86_64-sie-ps5 -x cl -c -emit-llvm -fno-visibility-from-dllstorageclass %s 2>&1 | \ +// RUN: FileCheck -check-prefixes=VDEFAULT,VGND_DEFAULT,NOVISFROM %s --implicit-check-not=fvisibility --implicit-check-not=ftype-visibility --implicit-check-not=dllstorageclass +// NOVISFROM-NOT: "-fvisibility-from-dllstorageclass" -- GitLab From ce1a0d8ad380d12dc7ea001cfab3749bb23d445d Mon Sep 17 00:00:00 2001 From: hanbeom Date: Mon, 20 May 2024 09:57:50 +0100 Subject: [PATCH 071/793] [AArch64] Optimize `MOV` to `ORR` when load symmetric constants (#86249) This change looks for cases of symmetric constant loading. `symmetric constant load` is when the upper 32 bits and lower 32 bits of a 64-bit register load the same value. When it finds this, it replaces it with an instruction that loads only the lower 32 bits of the constant and stores it in the upper and lower bits simultaneously. For example: renamable $x8 = MOVZXi 49370, 0 renamable $x8 = MOVKXi $x8, 320, 16 renamable $x8 = MOVKXi $x8, 49370, 32 renamable $x8 = MOVKXi $x8, 320, 48 becomes renamable $x8 = MOVZXi 49370, 0 renamable $x8 = MOVKXi $x8, 320, 16 renamable $x8 = ORRXrs $x8, $x8, 32 --- llvm/lib/Target/AArch64/AArch64ExpandImm.cpp | 8 ++++++++ .../lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp | 13 +++++++++++++ llvm/test/CodeGen/AArch64/movimm-expand-ldst.ll | 6 ++---- llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir | 6 ++---- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ExpandImm.cpp b/llvm/lib/Target/AArch64/AArch64ExpandImm.cpp index a7d72b59b1d5..98016271a9d0 100644 --- a/llvm/lib/Target/AArch64/AArch64ExpandImm.cpp +++ b/llvm/lib/Target/AArch64/AArch64ExpandImm.cpp @@ -518,6 +518,14 @@ static inline void expandMOVImmSimple(uint64_t Imm, unsigned BitSize, Insn.push_back({ Opc, Imm16, AArch64_AM::getShifterImm(AArch64_AM::LSL, Shift) }); } + + // Now, we get 16-bit divided Imm. If high and low bits are same in + // 32-bit, there is an opportunity to reduce instruction. + if (Insn.size() > 2 && (Imm >> 32) == (Imm & 0xffffffffULL)) { + for (int Size = Insn.size(); Size > 2; Size--) + Insn.pop_back(); + Insn.push_back({AArch64::ORRXrs, 0, 32}); + } } /// Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more diff --git a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp index 03f0778bae59..36957bb0f5a0 100644 --- a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp +++ b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp @@ -168,6 +168,19 @@ bool AArch64ExpandPseudo::expandMOVImm(MachineBasicBlock &MBB, .addImm(I->Op2)); } break; + case AArch64::ORRWrs: + case AArch64::ORRXrs: { + Register DstReg = MI.getOperand(0).getReg(); + bool DstIsDead = MI.getOperand(0).isDead(); + MIBS.push_back( + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode)) + .addReg(DstReg, RegState::Define | + getDeadRegState(DstIsDead && LastItem) | + RenamableState) + .addReg(DstReg) + .addReg(DstReg) + .addImm(I->Op2)); + } break; case AArch64::ANDXri: case AArch64::EORXri: if (I->Op1 == 0) { diff --git a/llvm/test/CodeGen/AArch64/movimm-expand-ldst.ll b/llvm/test/CodeGen/AArch64/movimm-expand-ldst.ll index 82bba7b5f854..b25ac96f97c7 100644 --- a/llvm/test/CodeGen/AArch64/movimm-expand-ldst.ll +++ b/llvm/test/CodeGen/AArch64/movimm-expand-ldst.ll @@ -6,8 +6,7 @@ define i64 @test0x1234567812345678() { ; CHECK: // %bb.0: ; CHECK-NEXT: mov x0, #22136 // =0x5678 ; CHECK-NEXT: movk x0, #4660, lsl #16 -; CHECK-NEXT: movk x0, #22136, lsl #32 -; CHECK-NEXT: movk x0, #4660, lsl #48 +; CHECK-NEXT: orr x0, x0, x0, lsl #32 ; CHECK-NEXT: ret ret i64 u0x1234567812345678 } @@ -17,8 +16,7 @@ define i64 @test0xff3456ffff3456ff() { ; CHECK: // %bb.0: ; CHECK-NEXT: mov x0, #22271 // =0x56ff ; CHECK-NEXT: movk x0, #65332, lsl #16 -; CHECK-NEXT: movk x0, #22271, lsl #32 -; CHECK-NEXT: movk x0, #65332, lsl #48 +; CHECK-NEXT: orr x0, x0, x0, lsl #32 ; CHECK-NEXT: ret ret i64 u0xff3456ffff3456ff } diff --git a/llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir b/llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir index de14437108c9..1ec2a00f6769 100644 --- a/llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir +++ b/llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir @@ -11,8 +11,7 @@ body: | ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: renamable $x0 = MOVZXi 49370, 0 ; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 320, 16 - ; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 49370, 32 - ; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 320, 48 + ; CHECK-NEXT: renamable $x0 = ORRXrs $x0, $x0, 32 ; CHECK-NEXT: RET undef $lr, implicit $x0 renamable $x0 = MOVi64imm 90284035103834330 RET_ReallyLR implicit $x0 @@ -28,8 +27,7 @@ body: | ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: renamable $x0 = MOVZXi 320, 0 ; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 49370, 16 - ; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 320, 32 - ; CHECK-NEXT: renamable $x0 = MOVKXi $x0, 49370, 48 + ; CHECK-NEXT: renamable $x0 = ORRXrs $x0, $x0, 32 ; CHECK-NEXT: RET undef $lr, implicit $x0 renamable $x0 = MOVi64imm -4550323095879417536 RET_ReallyLR implicit $x0 -- GitLab From 702a2b627ff4b2a5d330a7bd0d3f7cadaff0b4ed Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi Date: Mon, 20 May 2024 18:06:03 +0900 Subject: [PATCH 072/793] [Coverage] Rework !SystemHeadersCoverage (#91446) - Introduce `LeafExprSet`, - Suppress traversing LAnd and LOr expr under system headers. - Handle LAnd and LOr as instrumented leaves to override `!isInstrumentedCondition(C)`. - Replace Loc with FileLoc if it is expanded with system headers. Fixes #78920 --- clang/lib/CodeGen/CoverageMappingGen.cpp | 48 +++++++++++++++--- .../CoverageMapping/mcdc-system-headers.cpp | 50 +++++++++++++++++++ 2 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 clang/test/CoverageMapping/mcdc-system-headers.cpp diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index cc8ab7a5b436..f4de21bac4b4 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -17,6 +17,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Lex/Lexer.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ProfileData/Coverage/CoverageMapping.h" @@ -336,16 +337,26 @@ public: llvm::SmallSet Visited; SmallVector, 8> FileLocs; - for (const auto &Region : SourceRegions) { + for (auto &Region : SourceRegions) { SourceLocation Loc = Region.getBeginLoc(); + + // Replace Loc with FileLoc if it is expanded with system headers. + if (!SystemHeadersCoverage && SM.isInSystemMacro(Loc)) { + auto BeginLoc = SM.getSpellingLoc(Loc); + auto EndLoc = SM.getSpellingLoc(Region.getEndLoc()); + if (SM.isWrittenInSameFile(BeginLoc, EndLoc)) { + Loc = SM.getFileLoc(Loc); + Region.setStartLoc(Loc); + Region.setEndLoc(SM.getFileLoc(Region.getEndLoc())); + } + } + FileID File = SM.getFileID(Loc); if (!Visited.insert(File).second) continue; - // Do not map FileID's associated with system headers unless collecting - // coverage from system headers is explicitly enabled. - if (!SystemHeadersCoverage && SM.isInSystemHeader(SM.getSpellingLoc(Loc))) - continue; + assert(SystemHeadersCoverage || + !SM.isInSystemHeader(SM.getSpellingLoc(Loc))); unsigned Depth = 0; for (SourceLocation Parent = getIncludeOrExpansionLoc(Loc); @@ -818,6 +829,10 @@ struct CounterCoverageMappingBuilder /// A stack of currently live regions. llvm::SmallVector RegionStack; + /// Set if the Expr should be handled as a leaf even if it is kind of binary + /// logical ops (&&, ||). + llvm::DenseSet LeafExprSet; + /// An object to manage MCDC regions. MCDCCoverageBuilder MCDCBuilder; @@ -1040,7 +1055,10 @@ struct CounterCoverageMappingBuilder // region onto RegionStack but immediately pop it (which adds it to the // function's SourceRegions) because it doesn't apply to any other source // code other than the Condition. - if (CodeGenFunction::isInstrumentedCondition(C)) { + // With !SystemHeadersCoverage, binary logical ops in system headers may be + // treated as instrumentable conditions. + if (CodeGenFunction::isInstrumentedCondition(C) || + LeafExprSet.count(CodeGenFunction::stripCond(C))) { mcdc::Parameters BranchParams; mcdc::ConditionID ID = MCDCBuilder.getCondID(C); if (ID >= 0) @@ -2070,7 +2088,20 @@ struct CounterCoverageMappingBuilder createDecisionRegion(E, DecisionParams); } + /// Check if E belongs to system headers. + bool isExprInSystemHeader(const BinaryOperator *E) const { + return (!SystemHeadersCoverage && + SM.isInSystemHeader(SM.getSpellingLoc(E->getOperatorLoc())) && + SM.isInSystemHeader(SM.getSpellingLoc(E->getBeginLoc())) && + SM.isInSystemHeader(SM.getSpellingLoc(E->getEndLoc()))); + } + void VisitBinLAnd(const BinaryOperator *E) { + if (isExprInSystemHeader(E)) { + LeafExprSet.insert(E); + return; + } + bool IsRootNode = MCDCBuilder.isIdle(); // Keep track of Binary Operator and assign MCDC condition IDs. @@ -2125,6 +2156,11 @@ struct CounterCoverageMappingBuilder } void VisitBinLOr(const BinaryOperator *E) { + if (isExprInSystemHeader(E)) { + LeafExprSet.insert(E); + return; + } + bool IsRootNode = MCDCBuilder.isIdle(); // Keep track of Binary Operator and assign MCDC condition IDs. diff --git a/clang/test/CoverageMapping/mcdc-system-headers.cpp b/clang/test/CoverageMapping/mcdc-system-headers.cpp new file mode 100644 index 000000000000..a8a3ddbb506f --- /dev/null +++ b/clang/test/CoverageMapping/mcdc-system-headers.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -std=c++11 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -fcoverage-mcdc -mllvm -system-headers-coverage -emit-llvm-only -o - %s | FileCheck %s --check-prefixes=CHECK,W_SYS +// RUN: %clang_cc1 -std=c++11 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -fcoverage-mcdc -emit-llvm-only -o - %s | FileCheck %s --check-prefixes=CHECK,X_SYS + +#ifdef IS_SYSHEADER + +#pragma clang system_header +#define CONST 42 +#define EXPR1(x) (x) +#define EXPR2(x) ((x) && (x)) + +#else + +#define IS_SYSHEADER +#include __FILE__ + +// CHECK: _Z5func0i: +int func0(int a) { + // CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:21 = M:0, C:2 + // W_SYS: Expansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:16 = #0 (Expanded file = 1) + // X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = 0, 0 [1,2,0] + return (CONST && a); + // CHECK: Branch,File 0, [[@LINE-1]]:20 -> [[@LINE-1]]:21 = #2, (#1 - #2) [2,0,0] + // W_SYS: Branch,File 1, [[@LINE-16]]:15 -> [[@LINE-16]]:17 = 0, 0 [1,2,0] +} + +// CHECK: _Z5func1ii: +int func1(int a, int b) { + // CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:21 = M:0, C:2 + // CHECK: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:12 = (#0 - #1), #1 [1,0,2] + return (a || EXPR1(b)); + // W_SYS: Expansion,File 0, [[@LINE-1]]:16 -> [[@LINE-1]]:21 = #1 (Expanded file = 1) + // W_SYS: Branch,File 1, [[@LINE-24]]:18 -> [[@LINE-24]]:21 = (#1 - #2), #2 [2,0,0] + // X_SYS: Branch,File 0, [[@LINE-3]]:16 -> [[@LINE-3]]:16 = (#1 - #2), #2 [2,0,0] +} + +// CHECK: _Z5func2ii: +int func2(int a, int b) { + // W_SYS: Decision,File 0, [[@LINE+5]]:11 -> [[@LINE+5]]:28 = M:0, C:3 + // X_SYS: Decision,File 0, [[@LINE+4]]:11 -> [[@LINE+4]]:28 = M:0, C:2 + // W_SYS: Expansion,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:16 = #0 (Expanded file = 1) + // W_SYS: Expansion,File 0, [[@LINE+2]]:23 -> [[@LINE+2]]:28 = #1 (Expanded file = 2) + // X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = #1, (#0 - #1) [1,2,0] + return (EXPR2(a) && EXPR1(a)); + // W_SYS: Branch,File 1, [[@LINE-35]]:19 -> [[@LINE-35]]:22 = #3, (#0 - #3) [1,3,0] + // W_SYS: Branch,File 1, [[@LINE-36]]:26 -> [[@LINE-36]]:29 = #4, (#3 - #4) [3,2,0] + // W_SYS: Branch,File 2, [[@LINE-38]]:18 -> [[@LINE-38]]:21 = #2, (#1 - #2) [2,0,0] + // X_SYS: Branch,File 0, [[@LINE-4]]:23 -> [[@LINE-4]]:23 = #2, (#1 - #2) [2,0,0] +} + +#endif -- GitLab From 2217d1706a76d3f298899f824354ca9d96c45813 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilyev Date: Mon, 20 May 2024 13:44:52 +0400 Subject: [PATCH 073/793] [lldb][Windows] Fixed LibcxxChronoTimePointSecondsSummaryProvider() (#92701) This patch fixes #92574. It is a replacement for #92575. --- .../Plugins/Language/CPlusPlus/LibCxx.cpp | 11 ++++ .../chrono/TestDataFormatterLibcxxChrono.py | 57 ++++++++++++++++--- 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp index e160fd076393..b0e6fb7d6f5a 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -1098,6 +1098,7 @@ LibcxxChronoTimePointSecondsSummaryProvider(ValueObject &valobj, Stream &stream, if (!ptr_sp) return false; +#ifndef _WIN32 // The date time in the chrono library is valid in the range // [-32767-01-01T00:00:00Z, 32767-12-31T23:59:59Z]. A 64-bit time_t has a // larger range, the function strftime is not able to format the entire range @@ -1107,6 +1108,11 @@ LibcxxChronoTimePointSecondsSummaryProvider(ValueObject &valobj, Stream &stream, -1'096'193'779'200; // -32767-01-01T00:00:00Z const std::time_t chrono_timestamp_max = 971'890'963'199; // 32767-12-31T23:59:59Z +#else + const std::time_t chrono_timestamp_min = -43'200; // 1969-12-31T12:00:00Z + const std::time_t chrono_timestamp_max = + 32'536'850'399; // 3001-01-19T21:59:59 +#endif const std::time_t seconds = ptr_sp->GetValueAsSigned(0); if (seconds < chrono_timestamp_min || seconds > chrono_timestamp_max) @@ -1148,12 +1154,17 @@ LibcxxChronoTimepointDaysSummaryProvider(ValueObject &valobj, Stream &stream, if (!ptr_sp) return false; +#ifndef _WIN32 // The date time in the chrono library is valid in the range // [-32767-01-01Z, 32767-12-31Z]. A 32-bit time_t has a larger range, the // function strftime is not able to format the entire range of time_t. The // exact point has not been investigated; it's limited to chrono's range. const int chrono_timestamp_min = -12'687'428; // -32767-01-01Z const int chrono_timestamp_max = 11'248'737; // 32767-12-31Z +#else + const int chrono_timestamp_min = 0; // 1970-01-01Z + const int chrono_timestamp_max = 376'583; // 3001-01-19Z +#endif const int days = ptr_sp->GetValueAsSigned(0); if (days < chrono_timestamp_min || days > chrono_timestamp_max) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/chrono/TestDataFormatterLibcxxChrono.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/chrono/TestDataFormatterLibcxxChrono.py index fb35481d5551..0737a5bc7e6e 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/chrono/TestDataFormatterLibcxxChrono.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/chrono/TestDataFormatterLibcxxChrono.py @@ -14,6 +14,7 @@ class LibcxxChronoDataFormatterTestCase(TestBase): @skipIf(compiler="clang", compiler_version=["<", "17.0"]) def test_with_run_command(self): """Test that that file and class static variables display correctly.""" + isNotWindowsHost = lldbplatformutil.getHostPlatform() != "windows" self.build() (self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( self, "break here", lldb.SBFileSpec("main.cpp", False) @@ -57,7 +58,11 @@ class LibcxxChronoDataFormatterTestCase(TestBase): self.expect( "frame variable ss_neg_date_time", substrs=[ - "ss_neg_date_time = date/time=-32767-01-01T00:00:00Z timestamp=-1096193779200 s" + ( + "ss_neg_date_time = date/time=-32767-01-01T00:00:00Z timestamp=-1096193779200 s" + if isNotWindowsHost + else "ss_neg_date_time = timestamp=-1096193779200 s" + ) ], ) self.expect( @@ -68,7 +73,11 @@ class LibcxxChronoDataFormatterTestCase(TestBase): self.expect( "frame variable ss_pos_date_time", substrs=[ - "ss_pos_date_time = date/time=32767-12-31T23:59:59Z timestamp=971890963199 s" + ( + "ss_pos_date_time = date/time=32767-12-31T23:59:59Z timestamp=971890963199 s" + if isNotWindowsHost + else "ss_pos_date_time = timestamp=971890963199 s" + ) ], ) self.expect( @@ -103,7 +112,13 @@ class LibcxxChronoDataFormatterTestCase(TestBase): ) self.expect( "frame variable sd_neg_date", - substrs=["sd_neg_date = date=-32767-01-01Z timestamp=-12687428 days"], + substrs=[ + ( + "sd_neg_date = date=-32767-01-01Z timestamp=-12687428 days" + if isNotWindowsHost + else "sd_neg_date = timestamp=-12687428 days" + ) + ], ) self.expect( "frame variable sd_neg_days", @@ -112,7 +127,13 @@ class LibcxxChronoDataFormatterTestCase(TestBase): self.expect( "frame variable sd_pos_date", - substrs=["sd_pos_date = date=32767-12-31Z timestamp=11248737 days"], + substrs=[ + ( + "sd_pos_date = date=32767-12-31Z timestamp=11248737 days" + if isNotWindowsHost + else "sd_pos_date = timestamp=11248737 days" + ) + ], ) self.expect( "frame variable sd_pos_days", @@ -157,7 +178,11 @@ class LibcxxChronoDataFormatterTestCase(TestBase): self.expect( "frame variable ls_neg_date_time", substrs=[ - "ls_neg_date_time = date/time=-32767-01-01T00:00:00 timestamp=-1096193779200 s" + ( + "ls_neg_date_time = date/time=-32767-01-01T00:00:00 timestamp=-1096193779200 s" + if isNotWindowsHost + else "ls_neg_date_time = timestamp=-1096193779200 s" + ) ], ) self.expect( @@ -168,7 +193,11 @@ class LibcxxChronoDataFormatterTestCase(TestBase): self.expect( "frame variable ls_pos_date_time", substrs=[ - "ls_pos_date_time = date/time=32767-12-31T23:59:59 timestamp=971890963199 s" + ( + "ls_pos_date_time = date/time=32767-12-31T23:59:59 timestamp=971890963199 s" + if isNotWindowsHost + else "ls_pos_date_time = timestamp=971890963199 s" + ) ], ) self.expect( @@ -207,7 +236,13 @@ class LibcxxChronoDataFormatterTestCase(TestBase): ) self.expect( "frame variable ld_neg_date", - substrs=["ld_neg_date = date=-32767-01-01 timestamp=-12687428 days"], + substrs=[ + ( + "ld_neg_date = date=-32767-01-01 timestamp=-12687428 days" + if isNotWindowsHost + else "ld_neg_date = timestamp=-12687428 days" + ) + ], ) self.expect( "frame variable ld_neg_days", @@ -216,7 +251,13 @@ class LibcxxChronoDataFormatterTestCase(TestBase): self.expect( "frame variable ld_pos_date", - substrs=["ld_pos_date = date=32767-12-31 timestamp=11248737 days"], + substrs=[ + ( + "ld_pos_date = date=32767-12-31 timestamp=11248737 days" + if isNotWindowsHost + else "ld_pos_date = timestamp=11248737 days" + ) + ], ) self.expect( "frame variable ld_pos_days", -- GitLab From 8e8d2595dafa230a3da7f410200d89f05b6e8d87 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 20 May 2024 11:47:30 +0200 Subject: [PATCH 074/793] [ConstantFolding] Canonicalize constexpr GEPs to i8 (#89872) This patch canonicalizes constant expression GEPs to use i8 source element type, aka ptradd. This is the ConstantFolding equivalent of the InstCombine canonicalization introduced in #68882. I believe all our optimizations working on constant expression GEPs (like GlobalOpt etc) have already been switched to work on offsets, so I don't expect any significant fallout from this change. This is part of: https://discourse.llvm.org/t/rfc-replacing-getelementptr-with-ptradd/68699 --- clang/test/CodeGen/RISCV/riscv-inline-asm.c | 6 +- clang/test/CodeGen/attr-counted-by.c | 12 +- clang/test/CodeGenCXX/atomicinit.cpp | 4 +- clang/test/CodeGenCXX/auto-var-init.cpp | 4 +- .../test/Profile/c-unreachable-after-switch.c | 4 +- .../test/profile/Linux/counter_promo_for.c | 20 +- .../test/profile/Linux/counter_promo_while.c | 16 +- llvm/lib/Analysis/ConstantFolding.cpp | 46 +---- llvm/test/Other/constant-fold-gep.ll | 14 +- llvm/test/Other/optimize-inrange-gep.ll | 2 +- ...tion-specialization-constant-expression.ll | 6 +- llvm/test/Transforms/GVN/PRE/load-pre-licm.ll | 2 +- .../Transforms/GVN/PRE/phi-translate-2.ll | 4 +- .../test/Transforms/IndVarSimplify/D108043.ll | 2 +- .../IndVarSimplify/eliminate-exit-no-dl.ll | 2 +- .../IndVarSimplify/floating-point-small-iv.ll | 4 +- .../IndVarSimplify/lftr-dead-ivs.ll | 6 +- llvm/test/Transforms/IndVarSimplify/lftr.ll | 2 +- .../Transforms/InstCombine/addrspacecast.ll | 2 +- .../test/Transforms/InstCombine/align-addr.ll | 2 +- .../binop-select-cast-of-select-cond.ll | 2 +- .../constant-fold-address-space-pointer.ll | 2 +- .../InstCombine/constant-fold-gep.ll | 40 ++-- llvm/test/Transforms/InstCombine/fmul.ll | 2 +- .../InstCombine/force-opaque-ptr.ll | 4 +- .../Transforms/InstCombine/fortify-folding.ll | 4 +- .../Transforms/InstCombine/gep-custom-dl.ll | 6 +- .../Transforms/InstCombine/getelementptr.ll | 28 +-- ...hoist-xor-by-constant-from-xor-by-value.ll | 2 +- .../InstCombine/loadstore-alignment.ll | 4 +- llvm/test/Transforms/InstCombine/memchr-2.ll | 10 +- llvm/test/Transforms/InstCombine/memchr-4.ll | 2 +- llvm/test/Transforms/InstCombine/memchr-6.ll | 4 +- llvm/test/Transforms/InstCombine/memchr-7.ll | 2 +- llvm/test/Transforms/InstCombine/memchr-8.ll | 6 +- llvm/test/Transforms/InstCombine/memchr-9.ll | 36 ++-- llvm/test/Transforms/InstCombine/memchr.ll | 12 +- llvm/test/Transforms/InstCombine/memcmp-8.ll | 2 +- .../InstCombine/memcpy-from-global.ll | 8 +- llvm/test/Transforms/InstCombine/memrchr-3.ll | 20 +- llvm/test/Transforms/InstCombine/memrchr-4.ll | 4 +- .../merging-multiple-stores-into-successor.ll | 6 +- llvm/test/Transforms/InstCombine/objsize.ll | 4 +- llvm/test/Transforms/InstCombine/pr25342.ll | 10 +- llvm/test/Transforms/InstCombine/pr33453.ll | 2 +- .../InstCombine/pr38984-inseltpoison.ll | 2 +- llvm/test/Transforms/InstCombine/pr38984.ll | 2 +- llvm/test/Transforms/InstCombine/pr83947.ll | 4 +- .../InstCombine/ptr-replace-alloca.ll | 8 +- llvm/test/Transforms/InstCombine/rem.ll | 4 +- .../Transforms/InstCombine/select-and-or.ll | 4 +- .../InstCombine/simplify-libcalls-i16.ll | 10 +- .../InstCombine/simplify-libcalls.ll | 10 +- .../test/Transforms/InstCombine/snprintf-2.ll | 48 ++--- .../test/Transforms/InstCombine/snprintf-3.ll | 48 ++--- .../test/Transforms/InstCombine/snprintf-4.ll | 30 +-- llvm/test/Transforms/InstCombine/stpcpy-1.ll | 4 +- .../Transforms/InstCombine/stpcpy_chk-1.ll | 10 +- llvm/test/Transforms/InstCombine/stpncpy-1.ll | 35 ++-- llvm/test/Transforms/InstCombine/str-int-2.ll | 2 +- llvm/test/Transforms/InstCombine/str-int-3.ll | 4 +- llvm/test/Transforms/InstCombine/str-int-4.ll | 40 ++-- llvm/test/Transforms/InstCombine/str-int-5.ll | 50 ++--- llvm/test/Transforms/InstCombine/str-int.ll | 2 +- .../Transforms/InstCombine/strcall-bad-sig.ll | 10 +- .../Transforms/InstCombine/strcall-no-nul.ll | 20 +- llvm/test/Transforms/InstCombine/strchr-1.ll | 6 +- llvm/test/Transforms/InstCombine/strchr-3.ll | 12 +- llvm/test/Transforms/InstCombine/strcmp-4.ll | 4 +- llvm/test/Transforms/InstCombine/strlcpy-1.ll | 4 +- llvm/test/Transforms/InstCombine/strlen-1.ll | 2 +- llvm/test/Transforms/InstCombine/strlen-6.ll | 18 +- llvm/test/Transforms/InstCombine/strpbrk-1.ll | 2 +- llvm/test/Transforms/InstCombine/strrchr-1.ll | 6 +- llvm/test/Transforms/InstCombine/strrchr-3.ll | 8 +- llvm/test/Transforms/InstCombine/strstr-1.ll | 2 +- .../vec_demanded_elts-inseltpoison.ll | 2 +- .../InstCombine/vec_demanded_elts.ll | 2 +- llvm/test/Transforms/InstCombine/wcslen-1.ll | 4 +- .../InstSimplify/ConstProp/gep-alias.ll | 2 +- .../ConstProp/gep-constanfolding-error.ll | 3 +- .../Transforms/InstSimplify/ConstProp/gep.ll | 6 +- .../InstSimplify/ConstProp/icmp-global.ll | 10 +- llvm/test/Transforms/InstSimplify/compare.ll | 2 +- .../Transforms/InstSimplify/past-the-end.ll | 4 +- .../2011-12-19-PostincQuadratic.ll | 2 +- .../X86/2012-01-13-phielim.ll | 20 +- .../Transforms/LoopVectorize/X86/pr42674.ll | 2 +- ...pr47343-expander-lcssa-after-cfg-update.ll | 4 +- .../LoopVersioning/add-phi-update-users.ll | 6 +- .../bound-check-partially-known.ll | 10 +- llvm/test/Transforms/NewGVN/loadforward.ll | 2 +- .../PhaseOrdering/SystemZ/sub-xor.ll | 48 ++--- .../PhaseOrdering/X86/excessive-unrolling.ll | 180 +++++++++--------- .../Transforms/SCCP/2009-09-24-byval-ptr.ll | 2 +- llvm/test/Transforms/SCCP/apint-bigint2.ll | 6 +- .../SLPVectorizer/AArch64/gather-cost.ll | 8 +- .../Transforms/SLPVectorizer/X86/pr47623.ll | 28 +-- 98 files changed, 561 insertions(+), 585 deletions(-) diff --git a/clang/test/CodeGen/RISCV/riscv-inline-asm.c b/clang/test/CodeGen/RISCV/riscv-inline-asm.c index 3565705dea71..ed97add95e71 100644 --- a/clang/test/CodeGen/RISCV/riscv-inline-asm.c +++ b/clang/test/CodeGen/RISCV/riscv-inline-asm.c @@ -49,9 +49,9 @@ extern int var, arr[2][2]; struct Pair { int a, b; } pair; // CHECK-LABEL: test_s( -// CHECK: call void asm sideeffect "// $0 $1 $2", "s,s,s"(ptr nonnull @var, ptr nonnull getelementptr inbounds ([2 x [2 x i32]], ptr @arr, {{.*}}), ptr nonnull @test_s) -// CHECK: call void asm sideeffect "// $0", "s"(ptr nonnull getelementptr inbounds (%struct.Pair, ptr @pair, {{.*}})) -// CHECK: call void asm sideeffect "// $0 $1 $2", "S,S,S"(ptr nonnull @var, ptr nonnull getelementptr inbounds ([2 x [2 x i32]], ptr @arr, {{.*}}), ptr nonnull @test_s) +// CHECK: call void asm sideeffect "// $0 $1 $2", "s,s,s"(ptr nonnull @var, ptr nonnull getelementptr inbounds (i8, ptr @arr, {{.*}}), ptr nonnull @test_s) +// CHECK: call void asm sideeffect "// $0", "s"(ptr nonnull getelementptr inbounds (i8, ptr @pair, {{.*}})) +// CHECK: call void asm sideeffect "// $0 $1 $2", "S,S,S"(ptr nonnull @var, ptr nonnull getelementptr inbounds (i8, ptr @arr, {{.*}}), ptr nonnull @test_s) void test_s(void) { asm("// %0 %1 %2" :: "s"(&var), "s"(&arr[1][1]), "s"(test_s)); asm("// %0" :: "s"(&pair.b)); diff --git a/clang/test/CodeGen/attr-counted-by.c b/clang/test/CodeGen/attr-counted-by.c index de30a00138ac..79922eb4159f 100644 --- a/clang/test/CodeGen/attr-counted-by.c +++ b/clang/test/CodeGen/attr-counted-by.c @@ -1098,7 +1098,7 @@ int test12_a, test12_b; // SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB20:[0-9]+]], i64 0) #[[ATTR10]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // SANITIZE-WITH-ATTR: handler.type_mismatch6: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB21:[0-9]+]], i64 ptrtoint (ptr getelementptr inbounds ([[STRUCT_ANON_5:%.*]], ptr @test12_foo, i64 1, i32 0, i32 0, i32 0) to i64)) #[[ATTR10]], !nosanitize [[META2]] +// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB21:[0-9]+]], i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @test12_foo, i64 4) to i64)) #[[ATTR10]], !nosanitize [[META2]] // SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META2]] // // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local noundef i32 @test12( @@ -1111,7 +1111,7 @@ int test12_a, test12_b; // NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [6 x i32], ptr [[BAZ]], i64 0, i64 [[IDXPROM]] // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[TMP0]], ptr @test12_b, align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr getelementptr inbounds ([[STRUCT_ANON_5:%.*]], ptr @test12_foo, i64 1, i32 0, i32 0, i32 0), align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr getelementptr inbounds (i8, ptr @test12_foo, i64 4), align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[TMP1]], ptr @test12_a, align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITH-ATTR-NEXT: br label [[FOR_COND:%.*]] // NO-SANITIZE-WITH-ATTR: for.cond: @@ -1140,7 +1140,7 @@ int test12_a, test12_b; // SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 0) #[[ATTR8]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR: handler.type_mismatch6: -// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 ptrtoint (ptr getelementptr inbounds ([[STRUCT_ANON_5:%.*]], ptr @test12_foo, i64 1, i32 0, i32 0, i32 0) to i64)) #[[ATTR8]], !nosanitize [[META9]] +// SANITIZE-WITHOUT-ATTR-NEXT: tail call void @__ubsan_handle_type_mismatch_v1_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @test12_foo, i64 4) to i64)) #[[ATTR8]], !nosanitize [[META9]] // SANITIZE-WITHOUT-ATTR-NEXT: unreachable, !nosanitize [[META9]] // // NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local noundef i32 @test12( @@ -1153,7 +1153,7 @@ int test12_a, test12_b; // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [6 x i32], ptr [[BAZ]], i64 0, i64 [[IDXPROM]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[TMP0]], ptr @test12_b, align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr getelementptr inbounds ([[STRUCT_ANON_5:%.*]], ptr @test12_foo, i64 1, i32 0, i32 0, i32 0), align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr getelementptr inbounds (i8, ptr @test12_foo, i64 4), align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[TMP1]], ptr @test12_a, align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: br label [[FOR_COND:%.*]] // NO-SANITIZE-WITHOUT-ATTR: for.cond: @@ -1315,7 +1315,7 @@ int test14(int idx) { // NO-SANITIZE-WITH-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR4]] { // NO-SANITIZE-WITH-ATTR-NEXT: entry: // NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr getelementptr inbounds ([[STRUCT_ANON_8:%.*]], ptr @__const.test15.foo, i64 1, i32 0), i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr getelementptr inbounds (i8, ptr @__const.test15.foo, i64 8), i64 0, i64 [[IDXPROM]] // NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP0]] // @@ -1336,7 +1336,7 @@ int test14(int idx) { // NO-SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR1]] { // NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr getelementptr inbounds ([[STRUCT_ANON_8:%.*]], ptr @__const.test15.foo, i64 1, i32 0), i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr getelementptr inbounds (i8, ptr @__const.test15.foo, i64 8), i64 0, i64 [[IDXPROM]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] // NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP0]] // diff --git a/clang/test/CodeGenCXX/atomicinit.cpp b/clang/test/CodeGenCXX/atomicinit.cpp index f2398b020621..a568f17b90d0 100644 --- a/clang/test/CodeGenCXX/atomicinit.cpp +++ b/clang/test/CodeGenCXX/atomicinit.cpp @@ -86,7 +86,7 @@ namespace PR18097 { }; // CHECK-LABEL: define {{.*}} @__cxx_global_var_init // CHECK: call void @_ZN7PR180977dynamic1XC1Ei(ptr {{[^,]*}} @_ZN7PR180977dynamic1yE, i32 noundef 4) - // CHECK: store i32 5, ptr getelementptr inbounds ({{.*}}, ptr @_ZN7PR180977dynamic1yE, i32 0, i32 1) + // CHECK: store i32 5, ptr getelementptr inbounds (i8, ptr @_ZN7PR180977dynamic1yE, i32 4) Y y = { X(4), 5 }; } @@ -110,7 +110,7 @@ namespace PR18097 { // CHECK-LABEL: define {{.*}} @__cxx_global_var_init // CHECK: tail call void @llvm.memcpy.p0.p0.i32(ptr{{.*}} @_ZN7PR180978constant2y2E, ptr{{.*}} @_ZN7PR180978constantL1xE, i32 3, i1 false) // CHECK: %0 = load i32, ptr @_ZN7PR180978constant1zE - // CHECK: store i32 %0, ptr getelementptr inbounds (%"struct.PR18097::constant::Y", ptr @_ZN7PR180978constant2y2E, i32 0, i32 1) + // CHECK: store i32 %0, ptr getelementptr inbounds (i8, ptr @_ZN7PR180978constant2y2E, i32 4) int z; constexpr X x{1}; Y y2 = { x, z }; diff --git a/clang/test/CodeGenCXX/auto-var-init.cpp b/clang/test/CodeGenCXX/auto-var-init.cpp index 7803ed5b633f..e1568bee136e 100644 --- a/clang/test/CodeGenCXX/auto-var-init.cpp +++ b/clang/test/CodeGenCXX/auto-var-init.cpp @@ -1346,7 +1346,7 @@ TEST_UNINIT(base, base); // PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_base_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_base_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV4base, i64 0, i32 0, i64 2), {{.*}}, align 8 +// ZERO-O1: store ptr getelementptr inbounds inrange(-16, 16) (i8, ptr @_ZTV4base, i64 16), {{.*}}, align 8 // ZERO-O1-NOT: !annotation TEST_BRACES(base, base); @@ -1367,7 +1367,7 @@ TEST_UNINIT(derived, derived); // ZERO-LABEL: @test_derived_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0, {{.+}}), !annotation [[AUTO_INIT]] // ZERO-O1: store i64 0, {{.*}} align 8, !annotation [[AUTO_INIT]] -// ZERO-O1: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV7derived, i64 0, i32 0, i64 2), {{.*}} align 8 +// ZERO-O1: store ptr getelementptr inbounds inrange(-16, 16) (i8, ptr @_ZTV7derived, i64 16), {{.*}} align 8 TEST_BRACES(derived, derived); // CHECK-LABEL: @test_derived_braces() diff --git a/clang/test/Profile/c-unreachable-after-switch.c b/clang/test/Profile/c-unreachable-after-switch.c index 34d2742f7a3b..0ed2efa32e83 100644 --- a/clang/test/Profile/c-unreachable-after-switch.c +++ b/clang/test/Profile/c-unreachable-after-switch.c @@ -5,11 +5,11 @@ // CHECK-LABEL: @foo() // CHECK: store {{.*}} @[[C]] void foo(void) { - // CHECK: store {{.*}} @[[C]], i64 0, i64 2 + // CHECK: store {{.*}} @[[C]], i64 16) switch (0) { default: return; } // We shouldn't emit the unreachable counter. This used to crash in GlobalDCE. - // CHECK-NOT: store {{.*}} @[[C]], i64 0, i64 1} + // CHECK-NOT: store {{.*}} @[[C]], i64 8) } diff --git a/compiler-rt/test/profile/Linux/counter_promo_for.c b/compiler-rt/test/profile/Linux/counter_promo_for.c index 1694e3812de4..aa77e6084bf8 100644 --- a/compiler-rt/test/profile/Linux/counter_promo_for.c +++ b/compiler-rt/test/profile/Linux/counter_promo_for.c @@ -19,29 +19,29 @@ __attribute__((noinline)) void bar(int i) { g += i; } __attribute__((noinline)) void foo(int n, int N) { // PROMO-LABEL: @foo -// PROMO: load{{.*}}@__profc_foo{{.*}} 3){{.*}} +// PROMO: load{{.*}}@__profc_foo{{.*}} 24){{.*}} // PROMO-NEXT: add -// PROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 3){{.*}} +// PROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 24){{.*}} // PROMO: load{{.*}}@__profc_foo, align // PROMO-NEXT: add // PROMO-NEXT: store{{.*}}@__profc_foo, align -// PROMO-NEXT: load{{.*}}@__profc_foo{{.*}} 1){{.*}} +// PROMO-NEXT: load{{.*}}@__profc_foo{{.*}} 8){{.*}} // PROMO-NEXT: add -// PROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 1){{.*}} -// PROMO: load{{.*}}@__profc_foo{{.*}} 2){{.*}} +// PROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 8){{.*}} +// PROMO: load{{.*}}@__profc_foo{{.*}} 16){{.*}} // PROMO-NEXT: add -// PROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 2){{.*}} +// PROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 16){{.*}} // // NOPROMO-LABEL: @foo // NOPROMO: load{{.*}}@__profc_foo, align // NOPROMO-NEXT: add // NOPROMO-NEXT: store{{.*}}@__profc_foo, align -// NOPROMO: load{{.*}}@__profc_foo{{.*}} 1){{.*}} +// NOPROMO: load{{.*}}@__profc_foo{{.*}} 8){{.*}} // NOPROMO-NEXT: add -// NOPROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 1){{.*}} -// NOPROMO: load{{.*}}@__profc_foo{{.*}} 2){{.*}} +// NOPROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 8){{.*}} +// NOPROMO: load{{.*}}@__profc_foo{{.*}} 16){{.*}} // NOPROMO-NEXT: add -// NOPROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 2){{.*}} +// NOPROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 16){{.*}} int i; for (i = 0; i < N; i++) { if (i < n + 1) diff --git a/compiler-rt/test/profile/Linux/counter_promo_while.c b/compiler-rt/test/profile/Linux/counter_promo_while.c index 71c4a90d29fa..c6ea3a7282d4 100644 --- a/compiler-rt/test/profile/Linux/counter_promo_while.c +++ b/compiler-rt/test/profile/Linux/counter_promo_while.c @@ -20,23 +20,23 @@ __attribute__((noinline)) void foo(int n, int N) { // PROMO: load{{.*}}@__profc_foo, align // PROMO-NEXT: add // PROMO-NEXT: store{{.*}}@__profc_foo, align -// PROMO-NEXT: load{{.*}}@__profc_foo{{.*}} 1){{.*}} +// PROMO-NEXT: load{{.*}}@__profc_foo{{.*}} 8){{.*}} // PROMO-NEXT: add -// PROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 1){{.*}} -// PROMO-NEXT: load{{.*}}@__profc_foo{{.*}} 2){{.*}} +// PROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 8){{.*}} +// PROMO-NEXT: load{{.*}}@__profc_foo{{.*}} 16){{.*}} // PROMO-NEXT: add -// PROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 2){{.*}} +// PROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 16){{.*}} // // NOPROMO-LABEL: @foo // NOPROMO: load{{.*}}@__profc_foo, align // NOPROMO-NEXT: add // NOPROMO-NEXT: store{{.*}}@__profc_foo, align -// NOPROMO: load{{.*}}@__profc_foo{{.*}} 1){{.*}} +// NOPROMO: load{{.*}}@__profc_foo{{.*}} 8){{.*}} // NOPROMO-NEXT: add -// NOPROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 1){{.*}} -// NOPROMO: load{{.*}}@__profc_foo{{.*}} 2){{.*}} +// NOPROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 8){{.*}} +// NOPROMO: load{{.*}}@__profc_foo{{.*}} 16){{.*}} // NOPROMO-NEXT: add -// NOPROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 2){{.*}} +// NOPROMO-NEXT: store{{.*}}@__profc_foo{{.*}} 16){{.*}} int i = 0; while (i < N) { if (i < n + 1) diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 524e84f3f3de..31667ff3951f 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -869,7 +869,6 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, bool InBounds = GEP->isInBounds(); Type *SrcElemTy = GEP->getSourceElementType(); - Type *ResElemTy = GEP->getResultElementType(); Type *ResTy = GEP->getType(); if (!SrcElemTy->isSized() || isa(SrcElemTy)) return nullptr; @@ -944,43 +943,18 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, return ConstantExpr::getIntToPtr(C, ResTy); } - // Otherwise form a regular getelementptr. Recompute the indices so that - // we eliminate over-indexing of the notional static type array bounds. - // This makes it easy to determine if the getelementptr is "inbounds". - - // For GEPs of GlobalValues, use the value type, otherwise use an i8 GEP. - if (auto *GV = dyn_cast(Ptr)) - SrcElemTy = GV->getValueType(); - else - SrcElemTy = Type::getInt8Ty(Ptr->getContext()); - - if (!SrcElemTy->isSized()) - return nullptr; - - Type *ElemTy = SrcElemTy; - SmallVector Indices = DL.getGEPIndicesForOffset(ElemTy, Offset); - if (Offset != 0) - return nullptr; - - // Try to add additional zero indices to reach the desired result element - // type. - // TODO: Should we avoid extra zero indices if ResElemTy can't be reached and - // we'll have to insert a bitcast anyway? - while (ElemTy != ResElemTy) { - Type *NextTy = GetElementPtrInst::getTypeAtIndex(ElemTy, (uint64_t)0); - if (!NextTy) - break; - - Indices.push_back(APInt::getZero(isa(ElemTy) ? 32 : BitWidth)); - ElemTy = NextTy; + // Try to infer inbounds for GEPs of globals. + if (!InBounds && Offset.isNonNegative()) { + bool CanBeNull, CanBeFreed; + uint64_t DerefBytes = + Ptr->getPointerDereferenceableBytes(DL, CanBeNull, CanBeFreed); + InBounds = DerefBytes != 0 && !CanBeNull && Offset.sle(DerefBytes); } - SmallVector NewIdxs; - for (const APInt &Index : Indices) - NewIdxs.push_back(ConstantInt::get( - Type::getIntNTy(Ptr->getContext(), Index.getBitWidth()), Index)); - - return ConstantExpr::getGetElementPtr(SrcElemTy, Ptr, NewIdxs, InBounds, + // Otherwise canonicalize this to a single ptradd. + LLVMContext &Ctx = Ptr->getContext(); + return ConstantExpr::getGetElementPtr(Type::getInt8Ty(Ctx), Ptr, + ConstantInt::get(Ctx, Offset), InBounds, InRange); } diff --git a/llvm/test/Other/constant-fold-gep.ll b/llvm/test/Other/constant-fold-gep.ll index 0c1ca129bdb3..9af300ac9907 100644 --- a/llvm/test/Other/constant-fold-gep.ll +++ b/llvm/test/Other/constant-fold-gep.ll @@ -106,10 +106,10 @@ ; PLAIN: @Y = global ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @ext, i64 2) ; PLAIN: @Z = global ptr getelementptr inbounds (i32, ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @ext, i64 0, i64 1, i32 0), i64 1) -; OPT: @Y = local_unnamed_addr global ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @ext, i64 2) -; OPT: @Z = local_unnamed_addr global ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @ext, i64 0, i64 1, i32 1) -; TO: @Y = local_unnamed_addr global ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @ext, i64 2) -; TO: @Z = local_unnamed_addr global ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @ext, i64 0, i64 1, i32 1) +; OPT: @Y = local_unnamed_addr global ptr getelementptr inbounds (i8, ptr @ext, i64 48) +; OPT: @Z = local_unnamed_addr global ptr getelementptr inbounds (i8, ptr @ext, i64 12) +; TO: @Y = local_unnamed_addr global ptr getelementptr inbounds (i8, ptr @ext, i64 48) +; TO: @Z = local_unnamed_addr global ptr getelementptr inbounds (i8, ptr @ext, i64 12) @ext = external global [3 x { i32, i32 }] @Y = global ptr getelementptr inbounds ([3 x { i32, i32 }], ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @ext, i64 1), i64 1) @@ -433,10 +433,10 @@ define ptr @fO() nounwind { ; PLAIN: ret ptr %t ; PLAIN: } ; OPT: define ptr @fZ() local_unnamed_addr #0 { -; OPT: ret ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @ext, i64 0, i64 1, i32 1) +; OPT: ret ptr getelementptr inbounds (i8, ptr @ext, i64 12) ; OPT: } ; TO: define ptr @fZ() local_unnamed_addr #0 { -; TO: ret ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @ext, i64 0, i64 1, i32 1) +; TO: ret ptr getelementptr inbounds (i8, ptr @ext, i64 12) ; TO: } ; SCEV: Classifying expressions for: @fZ ; SCEV: %t = bitcast ptr getelementptr inbounds (i32, ptr getelementptr inbounds ([3 x { i32, i32 }], ptr @ext, i64 0, i64 1, i32 0), i64 1) to ptr @@ -464,7 +464,7 @@ define ptr @same_addrspace() nounwind noinline { ; OPT: same_addrspace %p = getelementptr inbounds i8, ptr @p0, i32 2 ret ptr %p -; OPT: ret ptr getelementptr inbounds ([4 x i8], ptr @p0, i64 0, i64 2) +; OPT: ret ptr getelementptr inbounds (i8, ptr @p0, i64 2) } @gv1 = internal global i32 1 diff --git a/llvm/test/Other/optimize-inrange-gep.ll b/llvm/test/Other/optimize-inrange-gep.ll index 2eae34bdb09b..e7465fddd80f 100644 --- a/llvm/test/Other/optimize-inrange-gep.ll +++ b/llvm/test/Other/optimize-inrange-gep.ll @@ -20,7 +20,7 @@ define void @foo(ptr %p) { ; ; CHECK-LABEL: define void @foo( ; CHECK-SAME: ptr nocapture writeonly [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { -; CHECK-NEXT: store ptr getelementptr inbounds inrange(-24, 0) ({ [3 x ptr] }, ptr @vtable, i64 1, i32 0, i64 0), ptr [[P]], align 8 +; CHECK-NEXT: store ptr getelementptr inbounds inrange(-24, 0) (i8, ptr @vtable, i64 24), ptr [[P]], align 8 ; CHECK-NEXT: ret void ; store ptr getelementptr inrange(-24, 0) ({ [3 x ptr], [3 x ptr] }, ptr @vtable, i32 0, i32 0, i32 3), ptr %p diff --git a/llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression.ll b/llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression.ll index c242816b91d4..16a468511631 100644 --- a/llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression.ll +++ b/llvm/test/Transforms/FunctionSpecialization/function-specialization-constant-expression.ll @@ -30,13 +30,13 @@ define internal i64 @zoo(i1 %flag) { ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[PLUS:%.*]], label [[MINUS:%.*]] ; CHECK: plus: -; CHECK-NEXT: [[TMP0:%.*]] = call i64 @func2.specialized.2(ptr getelementptr inbounds ([[STRUCT:%.*]], ptr @Global, i64 0, i32 3)) +; CHECK-NEXT: [[TMP0:%.*]] = call i64 @func2.specialized.2(ptr getelementptr inbounds (i8, ptr @Global, i64 8)) ; CHECK-NEXT: br label [[MERGE:%.*]] ; CHECK: minus: -; CHECK-NEXT: [[TMP1:%.*]] = call i64 @func2.specialized.1(ptr getelementptr inbounds ([[STRUCT]], ptr @Global, i64 0, i32 4)) +; CHECK-NEXT: [[TMP1:%.*]] = call i64 @func2.specialized.1(ptr getelementptr inbounds (i8, ptr @Global, i64 16)) ; CHECK-NEXT: br label [[MERGE]] ; CHECK: merge: -; CHECK-NEXT: [[TMP2:%.*]] = phi i64 [ ptrtoint (ptr getelementptr inbounds ([[STRUCT]], ptr @Global, i64 0, i32 3) to i64), [[PLUS]] ], [ ptrtoint (ptr getelementptr inbounds ([[STRUCT]], ptr @Global, i64 0, i32 4) to i64), [[MINUS]] ] +; CHECK-NEXT: [[TMP2:%.*]] = phi i64 [ ptrtoint (ptr getelementptr inbounds (i8, ptr @Global, i64 8) to i64), [[PLUS]] ], [ ptrtoint (ptr getelementptr inbounds (i8, ptr @Global, i64 16) to i64), [[MINUS]] ] ; CHECK-NEXT: ret i64 [[TMP2]] ; entry: diff --git a/llvm/test/Transforms/GVN/PRE/load-pre-licm.ll b/llvm/test/Transforms/GVN/PRE/load-pre-licm.ll index c52f46b4f63e..6a05d5b17dde 100644 --- a/llvm/test/Transforms/GVN/PRE/load-pre-licm.ll +++ b/llvm/test/Transforms/GVN/PRE/load-pre-licm.ll @@ -8,7 +8,7 @@ target triple = "i386-apple-darwin11.0.0" define void @Bubble() nounwind noinline { ; CHECK-LABEL: @Bubble( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP7_PRE:%.*]] = load i32, ptr getelementptr inbounds ([5001 x i32], ptr @sortlist, i32 0, i32 1), align 4 +; CHECK-NEXT: [[TMP7_PRE:%.*]] = load i32, ptr getelementptr inbounds (i8, ptr @sortlist, i32 4), align 4 ; CHECK-NEXT: br label [[WHILE_BODY5:%.*]] ; CHECK: while.body5: ; CHECK-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP7_PRE]], [[ENTRY:%.*]] ], [ [[TMP71:%.*]], [[IF_END:%.*]] ] diff --git a/llvm/test/Transforms/GVN/PRE/phi-translate-2.ll b/llvm/test/Transforms/GVN/PRE/phi-translate-2.ll index 46fde7a0a48c..bd54de4acd4f 100644 --- a/llvm/test/Transforms/GVN/PRE/phi-translate-2.ll +++ b/llvm/test/Transforms/GVN/PRE/phi-translate-2.ll @@ -63,8 +63,8 @@ define void @test2(i64 %i) { ; CHECK: if.then: ; CHECK-NEXT: [[CALL:%.*]] = tail call i64 (...) @goo() ; CHECK-NEXT: store i64 [[CALL]], ptr @g2, align 8 -; CHECK-NEXT: [[T2_PRE:%.*]] = load i64, ptr getelementptr inbounds ([100 x i64], ptr @a, i64 0, i64 3), align 8 -; CHECK-NEXT: [[T3_PRE:%.*]] = load i64, ptr getelementptr inbounds ([100 x i64], ptr @b, i64 0, i64 3), align 8 +; CHECK-NEXT: [[T2_PRE:%.*]] = load i64, ptr getelementptr inbounds (i8, ptr @a, i64 24), align 8 +; CHECK-NEXT: [[T3_PRE:%.*]] = load i64, ptr getelementptr inbounds (i8, ptr @b, i64 24), align 8 ; CHECK-NEXT: [[DOTPRE:%.*]] = mul nsw i64 [[T3_PRE]], [[T2_PRE]] ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: diff --git a/llvm/test/Transforms/IndVarSimplify/D108043.ll b/llvm/test/Transforms/IndVarSimplify/D108043.ll index ab95f0bb9039..cc553e205ad3 100644 --- a/llvm/test/Transforms/IndVarSimplify/D108043.ll +++ b/llvm/test/Transforms/IndVarSimplify/D108043.ll @@ -9,7 +9,7 @@ define internal fastcc void @func_2() unnamed_addr { ; CHECK-NEXT: lbl_2898.preheader: ; CHECK-NEXT: br label [[LBL_2898:%.*]] ; CHECK: lbl_2898.loopexit: -; CHECK-NEXT: store ptr getelementptr inbounds ([4 x [6 x i32]], ptr @g_2168, i64 0, i64 3, i64 1), ptr @g_1150, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @g_2168, i64 76), ptr @g_1150, align 8 ; CHECK-NEXT: br label [[LBL_2898]] ; CHECK: lbl_2898: ; CHECK-NEXT: br label [[FOR_COND884:%.*]] diff --git a/llvm/test/Transforms/IndVarSimplify/eliminate-exit-no-dl.ll b/llvm/test/Transforms/IndVarSimplify/eliminate-exit-no-dl.ll index e605512cb23b..a3c4002626a7 100644 --- a/llvm/test/Transforms/IndVarSimplify/eliminate-exit-no-dl.ll +++ b/llvm/test/Transforms/IndVarSimplify/eliminate-exit-no-dl.ll @@ -14,7 +14,7 @@ define void @foo() { ; CHECK-NEXT: bb: ; CHECK-NEXT: br label [[BB3:%.*]] ; CHECK: bb3: -; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr getelementptr inbounds ([0 x i8], ptr @global, i64 0, i64 1), align 1 +; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr getelementptr inbounds (i8, ptr @global, i64 1), align 1 ; CHECK-NEXT: br i1 false, label [[BB7:%.*]], label [[BB11:%.*]] ; CHECK: bb7: ; CHECK-NEXT: [[TMP8:%.*]] = zext i8 [[TMP6]] to i64 diff --git a/llvm/test/Transforms/IndVarSimplify/floating-point-small-iv.ll b/llvm/test/Transforms/IndVarSimplify/floating-point-small-iv.ll index 599e69c814d9..bebd314f7375 100644 --- a/llvm/test/Transforms/IndVarSimplify/floating-point-small-iv.ll +++ b/llvm/test/Transforms/IndVarSimplify/floating-point-small-iv.ll @@ -357,7 +357,7 @@ define void @uitofp_fptoui_range_with_negative() { ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: store i32 100, ptr getelementptr inbounds ([16777219 x i32], ptr @array, i64 0, i64 100), align 4 +; CHECK-NEXT: store i32 100, ptr getelementptr inbounds (i8, ptr @array, i64 400), align 4 ; CHECK-NEXT: br i1 false, label [[FOR_BODY]], label [[CLEANUP:%.*]] ; CHECK: cleanup: ; CHECK-NEXT: ret void @@ -418,7 +418,7 @@ define void @uitofp_fptosi_range_with_negative () { ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: store i32 100, ptr getelementptr inbounds ([16777219 x i32], ptr @array, i64 0, i64 100), align 4 +; CHECK-NEXT: store i32 100, ptr getelementptr inbounds (i8, ptr @array, i64 400), align 4 ; CHECK-NEXT: br i1 false, label [[FOR_BODY]], label [[CLEANUP:%.*]] ; CHECK: cleanup: ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/IndVarSimplify/lftr-dead-ivs.ll b/llvm/test/Transforms/IndVarSimplify/lftr-dead-ivs.ll index a628a5357f6d..6c15eb4af4f1 100644 --- a/llvm/test/Transforms/IndVarSimplify/lftr-dead-ivs.ll +++ b/llvm/test/Transforms/IndVarSimplify/lftr-dead-ivs.ll @@ -112,7 +112,7 @@ define void @dom_store_preinc() #0 { ; CHECK-NEXT: [[P_0:%.*]] = phi ptr [ @data, [[ENTRY:%.*]] ], [ [[TMP3:%.*]], [[LOOP]] ] ; CHECK-NEXT: store volatile i8 0, ptr [[P_0]], align 1 ; CHECK-NEXT: [[TMP3]] = getelementptr inbounds i8, ptr [[P_0]], i64 1 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne ptr [[P_0]], getelementptr ([240 x i8], ptr @data, i64 1, i64 5) +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne ptr [[P_0]], getelementptr (i8, ptr @data, i64 245) ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: ret void @@ -141,7 +141,7 @@ define void @dom_store_postinc() #0 { ; CHECK-NEXT: [[P_0:%.*]] = phi ptr [ @data, [[ENTRY:%.*]] ], [ [[TMP3:%.*]], [[LOOP]] ] ; CHECK-NEXT: [[TMP3]] = getelementptr inbounds i8, ptr [[P_0]], i64 1 ; CHECK-NEXT: store volatile i8 0, ptr [[TMP3]], align 1 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne ptr [[TMP3]], getelementptr ([240 x i8], ptr @data, i64 1, i64 6) +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne ptr [[TMP3]], getelementptr (i8, ptr @data, i64 246) ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: ret void @@ -170,7 +170,7 @@ define i8 @dom_load() #0 { ; CHECK-NEXT: [[P_0:%.*]] = phi ptr [ @data, [[ENTRY:%.*]] ], [ [[TMP3:%.*]], [[LOOP]] ] ; CHECK-NEXT: [[TMP3]] = getelementptr inbounds i8, ptr [[P_0]], i64 1 ; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[TMP3]], align 1 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne ptr [[TMP3]], getelementptr ([240 x i8], ptr @data, i64 1, i64 6) +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne ptr [[TMP3]], getelementptr (i8, ptr @data, i64 246) ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: [[V_LCSSA:%.*]] = phi i8 [ [[V]], [[LOOP]] ] diff --git a/llvm/test/Transforms/IndVarSimplify/lftr.ll b/llvm/test/Transforms/IndVarSimplify/lftr.ll index 7f4820f093e5..e37a34019ccd 100644 --- a/llvm/test/Transforms/IndVarSimplify/lftr.ll +++ b/llvm/test/Transforms/IndVarSimplify/lftr.ll @@ -196,7 +196,7 @@ define void @test_zext(ptr %a) #0 { ; CHECK-NEXT: [[T2:%.*]] = load i8, ptr [[DOT0]], align 1 ; CHECK-NEXT: [[T3]] = getelementptr inbounds i8, ptr [[P_0]], i64 1 ; CHECK-NEXT: store i8 [[T2]], ptr [[P_0]], align 1 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne ptr [[P_0]], getelementptr inbounds ([240 x i8], ptr @data, i64 0, i64 239) +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne ptr [[P_0]], getelementptr inbounds (i8, ptr @data, i64 239) ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/InstCombine/addrspacecast.ll b/llvm/test/Transforms/InstCombine/addrspacecast.ll index cbb88b9a09c9..35a1066a6b31 100644 --- a/llvm/test/Transforms/InstCombine/addrspacecast.ll +++ b/llvm/test/Transforms/InstCombine/addrspacecast.ll @@ -141,7 +141,7 @@ define i32 @memcpy_addrspacecast() nounwind { ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LOOP_BODY]] ] ; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_INC:%.*]], [[LOOP_BODY]] ] ; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[I]] to i16 -; CHECK-NEXT: [[PTR:%.*]] = getelementptr i8, ptr addrspace(2) getelementptr inbounds ([60 x i8], ptr addrspace(2) @const_array, i16 0, i16 4), i16 [[TMP0]] +; CHECK-NEXT: [[PTR:%.*]] = getelementptr i8, ptr addrspace(2) getelementptr inbounds (i8, ptr addrspace(2) @const_array, i16 4), i16 [[TMP0]] ; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr addrspace(2) [[PTR]], align 1 ; CHECK-NEXT: [[EXT:%.*]] = zext i8 [[LOAD]] to i32 ; CHECK-NEXT: [[SUM_INC]] = add i32 [[SUM]], [[EXT]] diff --git a/llvm/test/Transforms/InstCombine/align-addr.ll b/llvm/test/Transforms/InstCombine/align-addr.ll index facb5df08a82..58647dc9595d 100644 --- a/llvm/test/Transforms/InstCombine/align-addr.ll +++ b/llvm/test/Transforms/InstCombine/align-addr.ll @@ -81,7 +81,7 @@ define <16 x i8> @test1_as1(<2 x i64> %x) { define <16 x i8> @test1_as1_gep(<2 x i64> %x) { ; CHECK-LABEL: @test1_as1_gep( -; CHECK-NEXT: [[TMP:%.*]] = load <16 x i8>, ptr addrspace(1) getelementptr inbounds ([8 x i32], ptr addrspace(1) @GLOBAL_as1_gep, i32 0, i32 4), align 1 +; CHECK-NEXT: [[TMP:%.*]] = load <16 x i8>, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) @GLOBAL_as1_gep, i32 16), align 1 ; CHECK-NEXT: ret <16 x i8> [[TMP]] ; %tmp = load <16 x i8>, ptr addrspace(1) getelementptr ([8 x i32], ptr addrspace(1) @GLOBAL_as1_gep, i16 0, i16 4), align 1 diff --git a/llvm/test/Transforms/InstCombine/binop-select-cast-of-select-cond.ll b/llvm/test/Transforms/InstCombine/binop-select-cast-of-select-cond.ll index 7dc2fe1cb88e..b0da6d80d05a 100644 --- a/llvm/test/Transforms/InstCombine/binop-select-cast-of-select-cond.ll +++ b/llvm/test/Transforms/InstCombine/binop-select-cast-of-select-cond.ll @@ -232,7 +232,7 @@ define i64 @pr64669(i64 %a) { ; CHECK-LABEL: define i64 @pr64669 ; CHECK-SAME: (i64 [[A:%.*]]) { ; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[A]], 1 -; CHECK-NEXT: [[ADD:%.*]] = select i1 icmp ne (ptr getelementptr inbounds ([72 x i32], ptr @b, i64 0, i64 25), ptr @c), i64 [[TMP1]], i64 0 +; CHECK-NEXT: [[ADD:%.*]] = select i1 icmp ne (ptr getelementptr inbounds (i8, ptr @b, i64 100), ptr @c), i64 [[TMP1]], i64 0 ; CHECK-NEXT: ret i64 [[ADD]] ; %mul = select i1 icmp ne (ptr getelementptr inbounds ([72 x i32], ptr @b, i64 0, i64 25), ptr @c), i64 %a, i64 0 diff --git a/llvm/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll b/llvm/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll index 30d5cd66066b..857704f58028 100644 --- a/llvm/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll +++ b/llvm/test/Transforms/InstCombine/constant-fold-address-space-pointer.ll @@ -223,7 +223,7 @@ define i32 @test_cast_gep_large_indices_as() { define i32 @test_constant_cast_gep_struct_indices_as() { ; CHECK-LABEL: @test_constant_cast_gep_struct_indices_as( -; CHECK-NEXT: [[Y:%.*]] = load i32, ptr addrspace(3) getelementptr inbounds ([[STRUCT_FOO:%.*]], ptr addrspace(3) @constant_fold_global_ptr, i16 0, i32 2, i16 2), align 4 +; CHECK-NEXT: [[Y:%.*]] = load i32, ptr addrspace(3) getelementptr inbounds (i8, ptr addrspace(3) @constant_fold_global_ptr, i16 16), align 4 ; CHECK-NEXT: ret i32 [[Y]] ; %x = getelementptr %struct.foo, ptr addrspace(3) @constant_fold_global_ptr, i18 0, i32 2, i12 2 diff --git a/llvm/test/Transforms/InstCombine/constant-fold-gep.ll b/llvm/test/Transforms/InstCombine/constant-fold-gep.ll index 009c19dfa66c..54b7a6f66ecd 100644 --- a/llvm/test/Transforms/InstCombine/constant-fold-gep.ll +++ b/llvm/test/Transforms/InstCombine/constant-fold-gep.ll @@ -12,26 +12,26 @@ target datalayout = "E-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32- define void @frob() { ; CHECK-LABEL: @frob( ; CHECK-NEXT: store i32 1, ptr @Y, align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 1), align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 0, i64 2), align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 1, i64 0), align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 1, i64 1), align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 0, i32 1, i64 2), align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 1, i32 0, i64 0), align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 1, i32 0, i64 1), align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 1, i32 0, i64 2), align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 1, i32 1, i64 0), align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 1, i32 1, i64 1), align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 1, i32 1, i64 2), align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 2, i32 0, i64 0), align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 2, i32 0, i64 1), align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 2, i32 0, i64 2), align 8 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 2, i32 1, i64 0), align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 2, i32 1, i64 1), align 8 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 0, i64 2, i32 1, i64 2), align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %struct.X], ptr @Y, i64 1, i64 0, i32 0, i64 0), align 8 -; CHECK-NEXT: store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 2, i64 0, i32 0, i64 0), align 8 -; CHECK-NEXT: store i32 1, ptr getelementptr ([3 x %struct.X], ptr @Y, i64 1, i64 0, i32 0, i64 1), align 8 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 4), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 8), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 12), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 16), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 20), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 24), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 28), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 32), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 36), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 40), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 44), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 48), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 52), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 56), align 8 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 60), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 64), align 8 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 68), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr inbounds (i8, ptr @Y, i64 72), align 8 +; CHECK-NEXT: store i32 1, ptr getelementptr (i8, ptr @Y, i64 144), align 8 +; CHECK-NEXT: store i32 1, ptr getelementptr (i8, ptr @Y, i64 76), align 8 ; CHECK-NEXT: ret void ; store i32 1, ptr @Y, align 4 diff --git a/llvm/test/Transforms/InstCombine/fmul.ll b/llvm/test/Transforms/InstCombine/fmul.ll index 1526956c5b24..ae2df634b020 100644 --- a/llvm/test/Transforms/InstCombine/fmul.ll +++ b/llvm/test/Transforms/InstCombine/fmul.ll @@ -1131,7 +1131,7 @@ for.body: define double @fmul_negated_constant_expression(double %x) { ; CHECK-LABEL: @fmul_negated_constant_expression( -; CHECK-NEXT: [[FSUB:%.*]] = fneg double bitcast (i64 ptrtoint (ptr getelementptr inbounds ({ [2 x ptr] }, ptr @g, i64 1, i32 0, i64 0) to i64) to double) +; CHECK-NEXT: [[FSUB:%.*]] = fneg double bitcast (i64 ptrtoint (ptr getelementptr inbounds (i8, ptr @g, i64 16) to i64) to double) ; CHECK-NEXT: [[R:%.*]] = fmul double [[FSUB]], [[X:%.*]] ; CHECK-NEXT: ret double [[R]] ; diff --git a/llvm/test/Transforms/InstCombine/force-opaque-ptr.ll b/llvm/test/Transforms/InstCombine/force-opaque-ptr.ll index ccc34e9134de..3b799e2fb2d0 100644 --- a/llvm/test/Transforms/InstCombine/force-opaque-ptr.ll +++ b/llvm/test/Transforms/InstCombine/force-opaque-ptr.ll @@ -5,14 +5,14 @@ define ptr @gep_constexpr_gv_1() { ; CHECK-LABEL: @gep_constexpr_gv_1( -; CHECK-NEXT: ret ptr getelementptr inbounds ([16 x i16], ptr @g, i64 0, i64 10) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @g, i64 20) ; ret ptr getelementptr([16 x i16], ptr @g, i64 0, i64 10) } define ptr @gep_constexpr_gv_2() { ; CHECK-LABEL: @gep_constexpr_gv_2( -; CHECK-NEXT: ret ptr getelementptr inbounds ([16 x i16], ptr @g, i64 0, i64 12) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @g, i64 24) ; ret ptr getelementptr(i32, ptr getelementptr([16 x i16], ptr @g, i64 0, i64 10), i64 1) } diff --git a/llvm/test/Transforms/InstCombine/fortify-folding.ll b/llvm/test/Transforms/InstCombine/fortify-folding.ll index a6b5dc90c364..988726c99edb 100644 --- a/llvm/test/Transforms/InstCombine/fortify-folding.ll +++ b/llvm/test/Transforms/InstCombine/fortify-folding.ll @@ -39,7 +39,7 @@ define ptr @test_memccpy_tail() { define ptr @test_mempcpy() { ; CHECK-LABEL: @test_mempcpy( ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(15) @a, ptr noundef nonnull align 1 dereferenceable(15) @b, i64 15, i1 false) -; CHECK-NEXT: ret ptr getelementptr inbounds ([60 x i8], ptr @a, i64 0, i64 15) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a, i64 15) ; %ret = call ptr @__mempcpy_chk(ptr @a, ptr @b, i64 15, i64 -1) ret ptr %ret @@ -57,7 +57,7 @@ define ptr @test_not_mempcpy() { define ptr @test_mempcpy_tail() { ; CHECK-LABEL: @test_mempcpy_tail( ; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(15) @a, ptr noundef nonnull align 1 dereferenceable(15) @b, i64 15, i1 false) -; CHECK-NEXT: ret ptr getelementptr inbounds ([60 x i8], ptr @a, i64 0, i64 15) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a, i64 15) ; %ret = tail call ptr @__mempcpy_chk(ptr @a, ptr @b, i64 15, i64 -1) ret ptr %ret diff --git a/llvm/test/Transforms/InstCombine/gep-custom-dl.ll b/llvm/test/Transforms/InstCombine/gep-custom-dl.ll index d9449e05612c..e8eaf4e24f7e 100644 --- a/llvm/test/Transforms/InstCombine/gep-custom-dl.ll +++ b/llvm/test/Transforms/InstCombine/gep-custom-dl.ll @@ -34,7 +34,7 @@ define ptr @test2(ptr %I) { define void @test3(i8 %B) { ; This should be turned into a constexpr instead of being an instruction ; CHECK-LABEL: @test3( -; CHECK-NEXT: store i8 [[B:%.*]], ptr getelementptr inbounds ([10 x i8], ptr @Global, i32 0, i32 4), align 1 +; CHECK-NEXT: store i8 [[B:%.*]], ptr getelementptr inbounds (i8, ptr @Global, i32 4), align 1 ; CHECK-NEXT: ret void ; %A = getelementptr [10 x i8], ptr @Global, i32 0, i32 4 @@ -62,7 +62,7 @@ define void @test_evaluate_gep_nested_as_ptrs(ptr addrspace(2) %B) { define void @test_evaluate_gep_as_ptrs_array(ptr addrspace(2) %B) { ; CHECK-LABEL: @test_evaluate_gep_as_ptrs_array( -; CHECK-NEXT: store ptr addrspace(2) [[B:%.*]], ptr addrspace(1) getelementptr inbounds ([4 x ptr addrspace(2)], ptr addrspace(1) @arst, i32 0, i32 2), align 8 +; CHECK-NEXT: store ptr addrspace(2) [[B:%.*]], ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) @arst, i32 16), align 8 ; CHECK-NEXT: ret void ; @@ -168,7 +168,7 @@ define i32 @test10() { define i16 @constant_fold_custom_dl() { ; CHECK-LABEL: @constant_fold_custom_dl( ; CHECK-NEXT: entry: -; CHECK-NEXT: ret i16 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr inbounds ([1000 x i8], ptr addrspace(1) @X_as1, i32 1, i32 0), i16 sub (i16 0, i16 ptrtoint (ptr addrspace(1) @X_as1 to i16))) to i16) +; CHECK-NEXT: ret i16 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) @X_as1, i32 1000), i16 sub (i16 0, i16 ptrtoint (ptr addrspace(1) @X_as1 to i16))) to i16) ; entry: diff --git a/llvm/test/Transforms/InstCombine/getelementptr.ll b/llvm/test/Transforms/InstCombine/getelementptr.ll index 04b0c196ab51..307ed8d2b02b 100644 --- a/llvm/test/Transforms/InstCombine/getelementptr.ll +++ b/llvm/test/Transforms/InstCombine/getelementptr.ll @@ -63,7 +63,7 @@ define ptr @test4(ptr %I) { define void @test5(i8 %B) { ; This should be turned into a constexpr instead of being an instruction ; CHECK-LABEL: @test5( -; CHECK-NEXT: store i8 [[B:%.*]], ptr getelementptr inbounds ([10 x i8], ptr @Global, i64 0, i64 4), align 1 +; CHECK-NEXT: store i8 [[B:%.*]], ptr getelementptr inbounds (i8, ptr @Global, i64 4), align 1 ; CHECK-NEXT: ret void ; %A = getelementptr [10 x i8], ptr @Global, i64 0, i64 4 @@ -74,7 +74,7 @@ define void @test5(i8 %B) { define void @test5_as1(i8 %B) { ; This should be turned into a constexpr instead of being an instruction ; CHECK-LABEL: @test5_as1( -; CHECK-NEXT: store i8 [[B:%.*]], ptr addrspace(1) getelementptr inbounds ([10 x i8], ptr addrspace(1) @Global_as1, i16 0, i16 4), align 1 +; CHECK-NEXT: store i8 [[B:%.*]], ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) @Global_as1, i16 4), align 1 ; CHECK-NEXT: ret void ; %A = getelementptr [10 x i8], ptr addrspace(1) @Global_as1, i16 0, i16 4 @@ -102,7 +102,7 @@ define void @test_evaluate_gep_nested_as_ptrs(ptr addrspace(2) %B) { define void @test_evaluate_gep_as_ptrs_array(ptr addrspace(2) %B) { ; CHECK-LABEL: @test_evaluate_gep_as_ptrs_array( -; CHECK-NEXT: store ptr addrspace(2) [[B:%.*]], ptr addrspace(1) getelementptr inbounds ([4 x ptr addrspace(2)], ptr addrspace(1) @arst, i16 0, i16 2), align 4 +; CHECK-NEXT: store ptr addrspace(2) [[B:%.*]], ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) @arst, i16 8), align 4 ; CHECK-NEXT: ret void ; @@ -114,7 +114,7 @@ define void @test_evaluate_gep_as_ptrs_array(ptr addrspace(2) %B) { ; This should be turned into a constexpr instead of being an instruction define void @test_overaligned_vec(i8 %B) { ; CHECK-LABEL: @test_overaligned_vec( -; CHECK-NEXT: store i8 [[B:%.*]], ptr getelementptr inbounds ([10 x i8], ptr @Global, i64 0, i64 2), align 1 +; CHECK-NEXT: store i8 [[B:%.*]], ptr getelementptr inbounds (i8, ptr @Global, i64 2), align 1 ; CHECK-NEXT: ret void ; %A = getelementptr <2 x half>, ptr @Global, i64 0, i64 1 @@ -537,7 +537,7 @@ define i32 @test21() { define i1 @test22() { ; CHECK-LABEL: @test22( -; CHECK-NEXT: ret i1 icmp ult (ptr getelementptr inbounds (i32, ptr @A, i64 1), ptr getelementptr (i32, ptr @B, i64 2)) +; CHECK-NEXT: ret i1 icmp ult (ptr getelementptr inbounds (i8, ptr @A, i64 4), ptr getelementptr (i8, ptr @B, i64 8)) ; %C = icmp ult ptr getelementptr (i32, ptr @A, i64 1), getelementptr (i32, ptr @B, i64 2) @@ -828,7 +828,7 @@ entry: define i32 @test35() nounwind { ; CHECK-LABEL: @test35( -; CHECK-NEXT: [[TMP1:%.*]] = call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @"\01LC8", ptr nonnull getelementptr inbounds ([[T0:%.*]], ptr @s, i64 0, i32 1, i64 0)) #[[ATTR0]] +; CHECK-NEXT: [[TMP1:%.*]] = call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @"\01LC8", ptr nonnull getelementptr inbounds (i8, ptr @s, i64 8)) #[[ATTR0]] ; CHECK-NEXT: ret i32 0 ; call i32 (ptr, ...) @printf(ptr @"\01LC8", @@ -839,7 +839,7 @@ define i32 @test35() nounwind { ; Don't treat signed offsets as unsigned. define ptr @test36() nounwind { ; CHECK-LABEL: @test36( -; CHECK-NEXT: ret ptr getelementptr ([11 x i8], ptr @array, i64 -1, i64 10) +; CHECK-NEXT: ret ptr getelementptr (i8, ptr @array, i64 -1) ; ret ptr getelementptr ([11 x i8], ptr @array, i32 0, i64 -1) } @@ -1377,14 +1377,14 @@ define ptr @gep_of_gep_multiuse_var_and_var(ptr %p, i64 %idx, i64 %idx2) { define ptr @const_gep_global_di_i8_smaller() { ; CHECK-LABEL: @const_gep_global_di_i8_smaller( -; CHECK-NEXT: ret ptr getelementptr (i8, ptr @g_i32_di, i64 3) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @g_i32_di, i64 3) ; ret ptr getelementptr (i8, ptr @g_i32_di, i64 3) } define ptr @const_gep_global_di_i8_exact() { ; CHECK-LABEL: @const_gep_global_di_i8_exact( -; CHECK-NEXT: ret ptr getelementptr inbounds (i32, ptr @g_i32_di, i64 1) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @g_i32_di, i64 4) ; ret ptr getelementptr (i8, ptr @g_i32_di, i64 4) } @@ -1398,21 +1398,21 @@ define ptr @const_gep_global_di_i8_larger() { define ptr @const_gep_global_di_i64_larger() { ; CHECK-LABEL: @const_gep_global_di_i64_larger( -; CHECK-NEXT: ret ptr getelementptr (i32, ptr @g_i32_di, i64 2) +; CHECK-NEXT: ret ptr getelementptr (i8, ptr @g_i32_di, i64 8) ; ret ptr getelementptr (i64, ptr @g_i32_di, i64 1) } define ptr @const_gep_global_e_smaller() { ; CHECK-LABEL: @const_gep_global_e_smaller( -; CHECK-NEXT: ret ptr getelementptr (i8, ptr @g_i32_e, i64 3) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @g_i32_e, i64 3) ; ret ptr getelementptr (i8, ptr @g_i32_e, i64 3) } define ptr @const_gep_global_e_exact() { ; CHECK-LABEL: @const_gep_global_e_exact( -; CHECK-NEXT: ret ptr getelementptr inbounds (i32, ptr @g_i32_e, i64 1) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @g_i32_e, i64 4) ; ret ptr getelementptr (i8, ptr @g_i32_e, i64 4) } @@ -1433,7 +1433,7 @@ define ptr @const_gep_global_ew_smaller() { define ptr @const_gep_global_ew_exact() { ; CHECK-LABEL: @const_gep_global_ew_exact( -; CHECK-NEXT: ret ptr getelementptr (i32, ptr @g_i32_ew, i64 1) +; CHECK-NEXT: ret ptr getelementptr (i8, ptr @g_i32_ew, i64 4) ; ret ptr getelementptr (i8, ptr @g_i32_ew, i64 4) } @@ -1447,7 +1447,7 @@ define ptr @const_gep_global_ew_larger() { define ptr @const_gep_0xi8_global() { ; CHECK-LABEL: @const_gep_0xi8_global( -; CHECK-NEXT: ret ptr getelementptr ([0 x i8], ptr @g_0xi8_e, i64 0, i64 10) +; CHECK-NEXT: ret ptr getelementptr (i8, ptr @g_0xi8_e, i64 10) ; ret ptr getelementptr ([0 x i8], ptr @g_0xi8_e, i64 0, i64 10) } diff --git a/llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll b/llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll index db2c8e2f22f6..d75dbcf9c9b9 100644 --- a/llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll +++ b/llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll @@ -94,7 +94,7 @@ entry: define i16 @constantexpr2() { ; CHECK-LABEL: @constantexpr2( -; CHECK-NEXT: [[I1:%.*]] = zext i1 icmp ne (ptr getelementptr inbounds ([6 x [1 x i64]], ptr @global_constant3, i64 0, i64 5, i64 0), ptr @global_constant4) to i16 +; CHECK-NEXT: [[I1:%.*]] = zext i1 icmp ne (ptr getelementptr inbounds (i8, ptr @global_constant3, i64 40), ptr @global_constant4) to i16 ; CHECK-NEXT: [[I2:%.*]] = load ptr, ptr @global_constant5, align 1 ; CHECK-NEXT: [[I3:%.*]] = load i16, ptr [[I2]], align 1 ; CHECK-NEXT: [[I4:%.*]] = xor i16 [[I3]], [[I1]] diff --git a/llvm/test/Transforms/InstCombine/loadstore-alignment.ll b/llvm/test/Transforms/InstCombine/loadstore-alignment.ll index 1027468d6715..098f2eee52df 100644 --- a/llvm/test/Transforms/InstCombine/loadstore-alignment.ll +++ b/llvm/test/Transforms/InstCombine/loadstore-alignment.ll @@ -9,7 +9,7 @@ target datalayout = "E-p:64:64:64-p1:64:64:64-p2:32:32:32-a0:0:8-f32:32:32-f64:6 define <2 x i64> @static_hem() { ; CHECK-LABEL: @static_hem( -; CHECK-NEXT: [[L:%.*]] = load <2 x i64>, ptr getelementptr (<2 x i64>, ptr @x, i64 7), align 1 +; CHECK-NEXT: [[L:%.*]] = load <2 x i64>, ptr getelementptr (i8, ptr @x, i64 112), align 1 ; CHECK-NEXT: ret <2 x i64> [[L]] ; %t = getelementptr <2 x i64>, ptr @x, i32 7 @@ -66,7 +66,7 @@ define <2 x i64> @bar() { define void @static_hem_store(<2 x i64> %y) { ; CHECK-LABEL: @static_hem_store( -; CHECK-NEXT: store <2 x i64> [[Y:%.*]], ptr getelementptr (<2 x i64>, ptr @x, i64 7), align 1 +; CHECK-NEXT: store <2 x i64> [[Y:%.*]], ptr getelementptr (i8, ptr @x, i64 112), align 1 ; CHECK-NEXT: ret void ; %t = getelementptr <2 x i64>, ptr @x, i32 7 diff --git a/llvm/test/Transforms/InstCombine/memchr-2.ll b/llvm/test/Transforms/InstCombine/memchr-2.ll index 22aae6edcf92..2e85fe4ad1de 100644 --- a/llvm/test/Transforms/InstCombine/memchr-2.ll +++ b/llvm/test/Transforms/InstCombine/memchr-2.ll @@ -51,7 +51,7 @@ define ptr @fold_memchr_a12345_4_3() { define ptr @fold_memchr_a12345_3_3() { ; CHECK-LABEL: @fold_memchr_a12345_3_3( -; CHECK-NEXT: ret ptr getelementptr inbounds ([5 x i8], ptr @a12345, i64 0, i64 2) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a12345, i64 2) ; %res = call ptr @memchr(ptr @a12345, i32 3, i64 3) @@ -63,7 +63,7 @@ define ptr @fold_memchr_a12345_3_3() { define ptr @fold_memchr_a12345_3_9() { ; CHECK-LABEL: @fold_memchr_a12345_3_9( -; CHECK-NEXT: ret ptr getelementptr inbounds ([5 x i8], ptr @a12345, i64 0, i64 2) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a12345, i64 2) ; %res = call ptr @memchr(ptr @a12345, i32 3, i64 9) @@ -76,7 +76,7 @@ define ptr @fold_memchr_a12345_3_9() { define ptr @fold_memchr_a123f45_500_9() { ; CHECK-LABEL: @fold_memchr_a123f45_500_9( -; CHECK-NEXT: ret ptr getelementptr inbounds ([5 x i8], ptr @a123f45, i64 0, i64 3) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a123f45, i64 3) ; %res = call ptr @memchr(ptr @a123f45, i32 500, i64 9) @@ -89,7 +89,7 @@ define ptr @fold_memchr_a123f45_500_9() { define ptr @fold_a12345_3_n(i64 %n) { ; CHECK-LABEL: @fold_a12345_3_n( ; CHECK-NEXT: [[MEMCHR_CMP:%.*]] = icmp ult i64 [[N:%.*]], 3 -; CHECK-NEXT: [[RES:%.*]] = select i1 [[MEMCHR_CMP]], ptr null, ptr getelementptr inbounds ([5 x i8], ptr @a12345, i64 0, i64 2) +; CHECK-NEXT: [[RES:%.*]] = select i1 [[MEMCHR_CMP]], ptr null, ptr getelementptr inbounds (i8, ptr @a12345, i64 2) ; CHECK-NEXT: ret ptr [[RES]] ; @@ -104,7 +104,7 @@ define ptr @fold_a12345_3_n(i64 %n) { define ptr @fold_a12345_259_n(i64 %n) { ; CHECK-LABEL: @fold_a12345_259_n( ; CHECK-NEXT: [[MEMCHR_CMP:%.*]] = icmp ult i64 [[N:%.*]], 3 -; CHECK-NEXT: [[RES:%.*]] = select i1 [[MEMCHR_CMP]], ptr null, ptr getelementptr inbounds ([5 x i8], ptr @a12345, i64 0, i64 2) +; CHECK-NEXT: [[RES:%.*]] = select i1 [[MEMCHR_CMP]], ptr null, ptr getelementptr inbounds (i8, ptr @a12345, i64 2) ; CHECK-NEXT: ret ptr [[RES]] ; diff --git a/llvm/test/Transforms/InstCombine/memchr-4.ll b/llvm/test/Transforms/InstCombine/memchr-4.ll index 93884c73af62..9aec0f1dfe57 100644 --- a/llvm/test/Transforms/InstCombine/memchr-4.ll +++ b/llvm/test/Transforms/InstCombine/memchr-4.ll @@ -44,7 +44,7 @@ define ptr @call_memchr_ax_2_uimax_p2() { define ptr @fold_memchr_a12345_3_uimax_p2() { ; CHECK-LABEL: @fold_memchr_a12345_3_uimax_p2( -; CHECK-NEXT: ret ptr getelementptr inbounds ([5 x i8], ptr @a12345, i64 0, i64 2) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a12345, i64 2) ; %res = call ptr @memchr(ptr @a12345, i32 3, i64 4294967297) diff --git a/llvm/test/Transforms/InstCombine/memchr-6.ll b/llvm/test/Transforms/InstCombine/memchr-6.ll index 6243c464c6d3..28364a92f54d 100644 --- a/llvm/test/Transforms/InstCombine/memchr-6.ll +++ b/llvm/test/Transforms/InstCombine/memchr-6.ll @@ -69,7 +69,7 @@ define ptr @fold_memchr_a111122_c_n(i32 %C, i64 %N) { ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 2 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ugt i64 [[N:%.*]], 4 ; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[TMP2]], [[TMP3]] -; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP4]], ptr getelementptr inbounds ([6 x i8], ptr @a111122, i64 0, i64 4), ptr null +; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP4]], ptr getelementptr inbounds (i8, ptr @a111122, i64 4), ptr null ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i8 [[TMP1]], 1 ; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i64 [[N]], 0 ; CHECK-NEXT: [[TMP7:%.*]] = and i1 [[TMP6]], [[TMP5]] @@ -103,7 +103,7 @@ define ptr @call_memchr_a1110111_c_4(i32 %C) { ; CHECK-LABEL: @call_memchr_a1110111_c_4( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0 -; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds ([7 x i8], ptr @a1110111, i64 0, i64 3), ptr null +; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds (i8, ptr @a1110111, i64 3), ptr null ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8 [[TMP1]], 1 ; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP3]], ptr @a1110111, ptr [[MEMCHR_SEL1]] ; CHECK-NEXT: ret ptr [[MEMCHR_SEL2]] diff --git a/llvm/test/Transforms/InstCombine/memchr-7.ll b/llvm/test/Transforms/InstCombine/memchr-7.ll index 50072b5ca148..0b364cce656d 100644 --- a/llvm/test/Transforms/InstCombine/memchr-7.ll +++ b/llvm/test/Transforms/InstCombine/memchr-7.ll @@ -76,7 +76,7 @@ define ptr @memchr_no_zero_cmp2(i32 %c) { ; CHECK-LABEL: @memchr_no_zero_cmp2( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 10 -; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds ([2 x i8], ptr @.str.1, i64 0, i64 1), ptr null +; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds (i8, ptr @.str.1, i64 1), ptr null ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8 [[TMP1]], 13 ; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP3]], ptr @.str.1, ptr [[MEMCHR_SEL1]] ; CHECK-NEXT: ret ptr [[MEMCHR_SEL2]] diff --git a/llvm/test/Transforms/InstCombine/memchr-8.ll b/llvm/test/Transforms/InstCombine/memchr-8.ll index 0e878b77e40d..b2ac2e6eda9a 100644 --- a/llvm/test/Transforms/InstCombine/memchr-8.ll +++ b/llvm/test/Transforms/InstCombine/memchr-8.ll @@ -15,7 +15,7 @@ declare ptr @memrchr(ptr, i32, i64) define ptr @call_a_pi32max_p1() { ; CHECK-LABEL: @call_a_pi32max_p1( -; CHECK-NEXT: [[CHR:%.*]] = tail call ptr @memrchr(ptr noundef nonnull dereferenceable(2147483647) getelementptr inbounds (<{ i8, [4294967295 x i8] }>, ptr @a, i64 0, i32 1, i64 2147483647), i32 0, i64 2147483647) +; CHECK-NEXT: [[CHR:%.*]] = tail call ptr @memrchr(ptr noundef nonnull dereferenceable(2147483647) getelementptr inbounds (i8, ptr @a, i64 2147483648), i32 0, i64 2147483647) ; CHECK-NEXT: ret ptr [[CHR]] ; %ptr = getelementptr <{ i8, [4294967295 x i8] }>, ptr @a, i32 0, i32 1, i32 2147483647 @@ -28,7 +28,7 @@ define ptr @call_a_pi32max_p1() { define ptr @call_a_pi32max() { ; CHECK-LABEL: @call_a_pi32max( -; CHECK-NEXT: [[CHR:%.*]] = tail call ptr @memrchr(ptr noundef nonnull dereferenceable(2147483647) getelementptr inbounds (<{ i8, [4294967295 x i8] }>, ptr @a, i64 0, i32 1, i64 2147483648), i32 0, i64 2147483647) +; CHECK-NEXT: [[CHR:%.*]] = tail call ptr @memrchr(ptr noundef nonnull dereferenceable(2147483647) getelementptr inbounds (i8, ptr @a, i64 2147483649), i32 0, i64 2147483647) ; CHECK-NEXT: ret ptr [[CHR]] ; %ptr = getelementptr <{ i8, [4294967295 x i8] }>, ptr @a, i32 0, i32 1, i64 2147483648 @@ -42,7 +42,7 @@ define ptr @call_a_pi32max() { define ptr @call_a_pui32max() { ; CHECK-LABEL: @call_a_pui32max( -; CHECK-NEXT: [[CHR:%.*]] = tail call ptr @memrchr(ptr noundef nonnull dereferenceable(4294967295) getelementptr inbounds (<{ i8, [4294967295 x i8] }>, ptr @a, i64 0, i32 1, i64 0), i32 0, i64 4294967295) +; CHECK-NEXT: [[CHR:%.*]] = tail call ptr @memrchr(ptr noundef nonnull dereferenceable(4294967295) getelementptr inbounds (i8, ptr @a, i64 1), i32 0, i64 4294967295) ; CHECK-NEXT: ret ptr [[CHR]] ; %ptr = getelementptr <{ i8, [4294967295 x i8] }>, ptr @a, i32 0, i32 1, i32 0 diff --git a/llvm/test/Transforms/InstCombine/memchr-9.ll b/llvm/test/Transforms/InstCombine/memchr-9.ll index fe80c282eed5..7a5e6c3f863c 100644 --- a/llvm/test/Transforms/InstCombine/memchr-9.ll +++ b/llvm/test/Transforms/InstCombine/memchr-9.ll @@ -24,19 +24,19 @@ define void @fold_memchr_A_pIb_cst_cst(ptr %pchr) { ; CHECK-NEXT: [[PST_0_4_4:%.*]] = getelementptr i8, ptr [[PCHR]], i64 16 ; CHECK-NEXT: store ptr null, ptr [[PST_0_4_4]], align 8 ; CHECK-NEXT: [[PST_1_0_1:%.*]] = getelementptr i8, ptr [[PCHR]], i64 24 -; CHECK-NEXT: store ptr getelementptr (i8, ptr @a, i64 1), ptr [[PST_1_0_1]], align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @a, i64 1), ptr [[PST_1_0_1]], align 8 ; CHECK-NEXT: [[PST_1_0_3:%.*]] = getelementptr i8, ptr [[PCHR]], i64 32 -; CHECK-NEXT: store ptr getelementptr (i8, ptr @a, i64 1), ptr [[PST_1_0_3]], align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @a, i64 1), ptr [[PST_1_0_3]], align 8 ; CHECK-NEXT: [[PST_1_1_1:%.*]] = getelementptr i8, ptr [[PCHR]], i64 40 ; CHECK-NEXT: store ptr null, ptr [[PST_1_1_1]], align 8 ; CHECK-NEXT: [[PST_1_1_2:%.*]] = getelementptr i8, ptr [[PCHR]], i64 48 -; CHECK-NEXT: store ptr getelementptr inbounds ([1 x %struct.A], ptr @a, i64 0, i64 0, i32 0, i64 1), ptr [[PST_1_1_2]], align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @a, i64 2), ptr [[PST_1_1_2]], align 8 ; CHECK-NEXT: [[PST_1_3_3:%.*]] = getelementptr i8, ptr [[PCHR]], i64 56 ; CHECK-NEXT: store ptr null, ptr [[PST_1_3_3]], align 8 ; CHECK-NEXT: [[PST_1_3_4:%.*]] = getelementptr i8, ptr [[PCHR]], i64 64 ; CHECK-NEXT: store ptr null, ptr [[PST_1_3_4]], align 8 ; CHECK-NEXT: [[PST_1_3_6:%.*]] = getelementptr i8, ptr [[PCHR]], i64 80 -; CHECK-NEXT: store ptr getelementptr inbounds ([1 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 1), ptr [[PST_1_3_6]], align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @a, i64 6), ptr [[PST_1_3_6]], align 8 ; CHECK-NEXT: ret void ; @@ -110,25 +110,25 @@ define void @fold_memchr_A_pIb_cst_N(i64 %N, ptr %pchr) { ; CHECK-NEXT: store ptr [[CHR_0_0_N]], ptr [[PCHR:%.*]], align 8 ; CHECK-NEXT: [[PST_0_1_N:%.*]] = getelementptr i8, ptr [[PCHR]], i64 8 ; CHECK-NEXT: [[MEMCHR_CMP1:%.*]] = icmp ult i64 [[N]], 3 -; CHECK-NEXT: [[CHR_0_1_N:%.*]] = select i1 [[MEMCHR_CMP1]], ptr null, ptr getelementptr inbounds ([1 x %struct.A], ptr @a, i64 0, i64 0, i32 0, i64 1) +; CHECK-NEXT: [[CHR_0_1_N:%.*]] = select i1 [[MEMCHR_CMP1]], ptr null, ptr getelementptr inbounds (i8, ptr @a, i64 2) ; CHECK-NEXT: store ptr [[CHR_0_1_N]], ptr [[PST_0_1_N]], align 8 ; CHECK-NEXT: [[PST_0_4_N:%.*]] = getelementptr i8, ptr [[PCHR]], i64 16 ; CHECK-NEXT: store ptr null, ptr [[PST_0_4_N]], align 8 ; CHECK-NEXT: [[PST_1_0_N:%.*]] = getelementptr i8, ptr [[PCHR]], i64 24 ; CHECK-NEXT: [[MEMCHR_CMP2:%.*]] = icmp eq i64 [[N]], 0 -; CHECK-NEXT: [[CHR_1_0_N:%.*]] = select i1 [[MEMCHR_CMP2]], ptr null, ptr getelementptr (i8, ptr @a, i64 1) +; CHECK-NEXT: [[CHR_1_0_N:%.*]] = select i1 [[MEMCHR_CMP2]], ptr null, ptr getelementptr inbounds (i8, ptr @a, i64 1) ; CHECK-NEXT: store ptr [[CHR_1_0_N]], ptr [[PST_1_0_N]], align 8 ; CHECK-NEXT: [[PST_1_1_N:%.*]] = getelementptr i8, ptr [[PCHR]], i64 32 ; CHECK-NEXT: [[MEMCHR_CMP3:%.*]] = icmp ult i64 [[N]], 2 -; CHECK-NEXT: [[CHR_1_1_N:%.*]] = select i1 [[MEMCHR_CMP3]], ptr null, ptr getelementptr inbounds ([1 x %struct.A], ptr @a, i64 0, i64 0, i32 0, i64 1) +; CHECK-NEXT: [[CHR_1_1_N:%.*]] = select i1 [[MEMCHR_CMP3]], ptr null, ptr getelementptr inbounds (i8, ptr @a, i64 2) ; CHECK-NEXT: store ptr [[CHR_1_1_N]], ptr [[PST_1_1_N]], align 8 ; CHECK-NEXT: [[PST_1_2_N:%.*]] = getelementptr i8, ptr [[PCHR]], i64 40 ; CHECK-NEXT: [[MEMCHR_CMP4:%.*]] = icmp ult i64 [[N]], 4 -; CHECK-NEXT: [[CHR_1_2_N:%.*]] = select i1 [[MEMCHR_CMP4]], ptr null, ptr getelementptr inbounds ([1 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 0) +; CHECK-NEXT: [[CHR_1_2_N:%.*]] = select i1 [[MEMCHR_CMP4]], ptr null, ptr getelementptr inbounds (i8, ptr @a, i64 4) ; CHECK-NEXT: store ptr [[CHR_1_2_N]], ptr [[PST_1_2_N]], align 8 ; CHECK-NEXT: [[PST_1_3_N:%.*]] = getelementptr i8, ptr [[PCHR]], i64 48 ; CHECK-NEXT: [[MEMCHR_CMP5:%.*]] = icmp ult i64 [[N]], 6 -; CHECK-NEXT: [[CHR_1_3_N:%.*]] = select i1 [[MEMCHR_CMP5]], ptr null, ptr getelementptr inbounds ([1 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 1) +; CHECK-NEXT: [[CHR_1_3_N:%.*]] = select i1 [[MEMCHR_CMP5]], ptr null, ptr getelementptr inbounds (i8, ptr @a, i64 6) ; CHECK-NEXT: store ptr [[CHR_1_3_N]], ptr [[PST_1_3_N]], align 8 ; CHECK-NEXT: [[PST_1_4_N:%.*]] = getelementptr i8, ptr [[PCHR]], i64 56 ; CHECK-NEXT: store ptr null, ptr [[PST_1_4_N]], align 8 @@ -136,15 +136,15 @@ define void @fold_memchr_A_pIb_cst_N(i64 %N, ptr %pchr) { ; CHECK-NEXT: store ptr null, ptr [[PST_2_0_N]], align 8 ; CHECK-NEXT: [[PST_2_1_N:%.*]] = getelementptr i8, ptr [[PCHR]], i64 72 ; CHECK-NEXT: [[MEMCHR_CMP6:%.*]] = icmp eq i64 [[N]], 0 -; CHECK-NEXT: [[CHR_2_1_N:%.*]] = select i1 [[MEMCHR_CMP6]], ptr null, ptr getelementptr inbounds ([1 x %struct.A], ptr @a, i64 0, i64 0, i32 0, i64 1) +; CHECK-NEXT: [[CHR_2_1_N:%.*]] = select i1 [[MEMCHR_CMP6]], ptr null, ptr getelementptr inbounds (i8, ptr @a, i64 2) ; CHECK-NEXT: store ptr [[CHR_2_1_N]], ptr [[PST_2_1_N]], align 8 ; CHECK-NEXT: [[PST_2_2_N:%.*]] = getelementptr i8, ptr [[PCHR]], i64 80 ; CHECK-NEXT: [[MEMCHR_CMP7:%.*]] = icmp ult i64 [[N]], 3 -; CHECK-NEXT: [[CHR_2_2_N:%.*]] = select i1 [[MEMCHR_CMP7]], ptr null, ptr getelementptr inbounds ([1 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 0) +; CHECK-NEXT: [[CHR_2_2_N:%.*]] = select i1 [[MEMCHR_CMP7]], ptr null, ptr getelementptr inbounds (i8, ptr @a, i64 4) ; CHECK-NEXT: store ptr [[CHR_2_2_N]], ptr [[PST_2_2_N]], align 8 ; CHECK-NEXT: [[PST_2_3_N:%.*]] = getelementptr i8, ptr [[PCHR]], i64 88 ; CHECK-NEXT: [[MEMCHR_CMP8:%.*]] = icmp ult i64 [[N]], 5 -; CHECK-NEXT: [[CHR_2_3_N:%.*]] = select i1 [[MEMCHR_CMP8]], ptr null, ptr getelementptr inbounds ([1 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 1) +; CHECK-NEXT: [[CHR_2_3_N:%.*]] = select i1 [[MEMCHR_CMP8]], ptr null, ptr getelementptr inbounds (i8, ptr @a, i64 6) ; CHECK-NEXT: store ptr [[CHR_2_3_N]], ptr [[PST_2_3_N]], align 8 ; CHECK-NEXT: [[PST_2_4_N:%.*]] = getelementptr i8, ptr [[PCHR]], i64 96 ; CHECK-NEXT: store ptr null, ptr [[PST_2_4_N]], align 8 @@ -230,13 +230,13 @@ define void @fold_memchr_A_pIb_cst_N(i64 %N, ptr %pchr) { define void @call_memchr_A_pIb_xs_cst(ptr %pchr) { ; CHECK-LABEL: @call_memchr_A_pIb_xs_cst( -; CHECK-NEXT: [[CHR_1_0_0_2:%.*]] = call ptr @memchr(ptr noundef nonnull dereferenceable(1) getelementptr inbounds ([1 x %struct.A], ptr @a, i64 1, i64 0), i32 0, i64 2) +; CHECK-NEXT: [[CHR_1_0_0_2:%.*]] = call ptr @memchr(ptr noundef nonnull dereferenceable(1) getelementptr inbounds (i8, ptr @a, i64 8), i32 0, i64 2) ; CHECK-NEXT: store ptr [[CHR_1_0_0_2]], ptr [[PCHR:%.*]], align 8 ; CHECK-NEXT: [[PST_1_0_1_2:%.*]] = getelementptr i8, ptr [[PCHR]], i64 8 -; CHECK-NEXT: [[CHR_1_0_1_2:%.*]] = call ptr @memchr(ptr noundef nonnull dereferenceable(1) getelementptr inbounds ([1 x %struct.A], ptr @a, i64 1, i64 0), i32 0, i64 2) +; CHECK-NEXT: [[CHR_1_0_1_2:%.*]] = call ptr @memchr(ptr noundef nonnull dereferenceable(1) getelementptr inbounds (i8, ptr @a, i64 8), i32 0, i64 2) ; CHECK-NEXT: store ptr [[CHR_1_0_1_2]], ptr [[PST_1_0_1_2]], align 8 ; CHECK-NEXT: [[PST_0_0_8_2:%.*]] = getelementptr i8, ptr [[PCHR]], i64 16 -; CHECK-NEXT: [[CHR_0_0_8_2:%.*]] = call ptr @memchr(ptr noundef nonnull dereferenceable(1) getelementptr inbounds ([1 x %struct.A], ptr @a, i64 1, i64 0, i32 0, i64 0), i32 0, i64 2) +; CHECK-NEXT: [[CHR_0_0_8_2:%.*]] = call ptr @memchr(ptr noundef nonnull dereferenceable(1) getelementptr inbounds (i8, ptr @a, i64 8), i32 0, i64 2) ; CHECK-NEXT: store ptr [[CHR_0_0_8_2]], ptr [[PST_0_0_8_2]], align 8 ; CHECK-NEXT: ret void ; @@ -276,7 +276,7 @@ define void @call_memchr_A_pIb_xs_cst(ptr %pchr) { define ptr @fold_memchr_gep_gep_gep() { ; CHECK-LABEL: @fold_memchr_gep_gep_gep( -; CHECK-NEXT: ret ptr getelementptr (i16, ptr getelementptr (i32, ptr getelementptr inbounds ([2 x i64], ptr @ai64, i64 0, i64 1), i64 1), i64 1) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @ai64, i64 14) ; %p8_1 = getelementptr [2 x i64], ptr @ai64, i64 0, i64 1 @@ -297,10 +297,10 @@ define ptr @fold_memchr_gep_gep_gep() { define ptr @fold_memchr_union_member() { ; BE-CHECK-LABEL: @fold_memchr_union_member( -; BE-CHECK-NEXT: ret ptr getelementptr (i8, ptr @u, i64 5) +; BE-CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @u, i64 5) ; ; LE-CHECK-LABEL: @fold_memchr_union_member( -; LE-CHECK-NEXT: ret ptr getelementptr inbounds ([[UNION_U:%.*]], ptr @u, i64 0, i32 0, i64 1) +; LE-CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @u, i64 4) ; %pi8u_p1 = getelementptr i8, ptr @u, i64 1 %pc = call ptr @memchr(ptr %pi8u_p1, i32 34, i64 8) diff --git a/llvm/test/Transforms/InstCombine/memchr.ll b/llvm/test/Transforms/InstCombine/memchr.ll index 2074fd7ba4f7..08435a5e0388 100644 --- a/llvm/test/Transforms/InstCombine/memchr.ll +++ b/llvm/test/Transforms/InstCombine/memchr.ll @@ -17,7 +17,7 @@ declare ptr @memchr(ptr, i32, i32) define void @test1() { ; CHECK-LABEL: @test1( -; CHECK-NEXT: store ptr getelementptr inbounds ([14 x i8], ptr @hello, i32 0, i32 6), ptr @chp, align 4 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @hello, i32 6), ptr @chp, align 4 ; CHECK-NEXT: ret void ; %dst = call ptr @memchr(ptr @hello, i32 119, i32 14) @@ -37,7 +37,7 @@ define void @test2() { define void @test3() { ; CHECK-LABEL: @test3( -; CHECK-NEXT: store ptr getelementptr inbounds ([14 x i8], ptr @hello, i32 0, i32 13), ptr @chp, align 4 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @hello, i32 13), ptr @chp, align 4 ; CHECK-NEXT: ret void ; %dst = call ptr @memchr(ptr @hello, i32 0, i32 14) @@ -58,7 +58,7 @@ define void @test4(i32 %chr) { define void @test5() { ; CHECK-LABEL: @test5( -; CHECK-NEXT: store ptr getelementptr inbounds ([14 x i8], ptr @hello, i32 0, i32 13), ptr @chp, align 4 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @hello, i32 13), ptr @chp, align 4 ; CHECK-NEXT: ret void ; %dst = call ptr @memchr(ptr @hello, i32 65280, i32 14) @@ -68,7 +68,7 @@ define void @test5() { define void @test6() { ; CHECK-LABEL: @test6( -; CHECK-NEXT: store ptr getelementptr inbounds ([14 x i8], ptr @hello, i32 0, i32 6), ptr @chp, align 4 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @hello, i32 6), ptr @chp, align 4 ; CHECK-NEXT: ret void ; ; Overflow, but we still find the right thing. @@ -90,7 +90,7 @@ define void @test7() { define void @test8() { ; CHECK-LABEL: @test8( -; CHECK-NEXT: store ptr getelementptr inbounds ([14 x i8], ptr @hellonull, i32 0, i32 6), ptr @chp, align 4 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @hellonull, i32 6), ptr @chp, align 4 ; CHECK-NEXT: ret void ; %dst = call ptr @memchr(ptr @hellonull, i32 119, i32 14) @@ -100,7 +100,7 @@ define void @test8() { define void @test9() { ; CHECK-LABEL: @test9( -; CHECK-NEXT: store ptr getelementptr inbounds ([14 x i8], ptr @hellonull, i32 0, i32 6), ptr @chp, align 4 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @hellonull, i32 6), ptr @chp, align 4 ; CHECK-NEXT: ret void ; %str = getelementptr [14 x i8], ptr @hellonull, i32 0, i32 2 diff --git a/llvm/test/Transforms/InstCombine/memcmp-8.ll b/llvm/test/Transforms/InstCombine/memcmp-8.ll index a3759914ad4f..2bc1efad5c77 100644 --- a/llvm/test/Transforms/InstCombine/memcmp-8.ll +++ b/llvm/test/Transforms/InstCombine/memcmp-8.ll @@ -42,7 +42,7 @@ define i32 @fold_memcmp_a5pi_a5p5_n(i32 %i, i64 %n) { ; CHECK-LABEL: @fold_memcmp_a5pi_a5p5_n( ; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[I:%.*]] to i64 ; CHECK-NEXT: [[PA5_PI:%.*]] = getelementptr [5 x i8], ptr @a5, i64 0, i64 [[TMP1]] -; CHECK-NEXT: [[CMP:%.*]] = call i32 @memcmp(ptr [[PA5_PI]], ptr nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0), i64 [[N:%.*]]) +; CHECK-NEXT: [[CMP:%.*]] = call i32 @memcmp(ptr [[PA5_PI]], ptr nonnull getelementptr inbounds (i8, ptr @a5, i64 5), i64 [[N:%.*]]) ; CHECK-NEXT: ret i32 [[CMP]] ; %pa5_pi = getelementptr [5 x i8], ptr @a5, i32 0, i32 %i diff --git a/llvm/test/Transforms/InstCombine/memcpy-from-global.ll b/llvm/test/Transforms/InstCombine/memcpy-from-global.ll index e9ff34735f1c..34e6c601f494 100644 --- a/llvm/test/Transforms/InstCombine/memcpy-from-global.ll +++ b/llvm/test/Transforms/InstCombine/memcpy-from-global.ll @@ -220,7 +220,7 @@ define void @test7() { define void @test8() { ; CHECK-LABEL: @test8( ; CHECK-NEXT: [[AL:%.*]] = alloca [[U:%.*]], align 16 -; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 16 dereferenceable(20) [[AL]], ptr noundef nonnull align 4 dereferenceable(20) getelementptr inbounds ([2 x %U], ptr @H, i64 0, i64 1), i64 20, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 16 dereferenceable(20) [[AL]], ptr noundef nonnull align 4 dereferenceable(20) getelementptr inbounds (i8, ptr @H, i64 20), i64 20, i1 false) ; CHECK-NEXT: call void @bar(ptr nonnull [[AL]]) #[[ATTR3]] ; CHECK-NEXT: ret void ; @@ -234,7 +234,7 @@ define void @test8() { define void @test8_addrspacecast() { ; CHECK-LABEL: @test8_addrspacecast( ; CHECK-NEXT: [[AL:%.*]] = alloca [[U:%.*]], align 16 -; CHECK-NEXT: call void @llvm.memcpy.p0.p1.i64(ptr noundef nonnull align 16 dereferenceable(20) [[AL]], ptr addrspace(1) noundef align 4 dereferenceable(20) addrspacecast (ptr getelementptr inbounds ([2 x %U], ptr @H, i64 0, i64 1) to ptr addrspace(1)), i64 20, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0.p1.i64(ptr noundef nonnull align 16 dereferenceable(20) [[AL]], ptr addrspace(1) noundef align 4 dereferenceable(20) addrspacecast (ptr getelementptr inbounds (i8, ptr @H, i64 20) to ptr addrspace(1)), i64 20, i1 false) ; CHECK-NEXT: call void @bar(ptr nonnull [[AL]]) #[[ATTR3]] ; CHECK-NEXT: ret void ; @@ -246,7 +246,7 @@ define void @test8_addrspacecast() { define void @test9() { ; CHECK-LABEL: @test9( -; CHECK-NEXT: call void @bar(ptr nonnull getelementptr inbounds ([2 x %U], ptr @H, i64 0, i64 1)) #[[ATTR3]] +; CHECK-NEXT: call void @bar(ptr nonnull getelementptr inbounds (i8, ptr @H, i64 20)) #[[ATTR3]] ; CHECK-NEXT: ret void ; %A = alloca %U, align 4 @@ -257,7 +257,7 @@ define void @test9() { define void @test9_addrspacecast() { ; CHECK-LABEL: @test9_addrspacecast( -; CHECK-NEXT: call void @bar(ptr nonnull getelementptr inbounds ([2 x %U], ptr @H, i64 0, i64 1)) #[[ATTR3]] +; CHECK-NEXT: call void @bar(ptr nonnull getelementptr inbounds (i8, ptr @H, i64 20)) #[[ATTR3]] ; CHECK-NEXT: ret void ; %A = alloca %U, align 4 diff --git a/llvm/test/Transforms/InstCombine/memrchr-3.ll b/llvm/test/Transforms/InstCombine/memrchr-3.ll index ca122e5b7dea..d3619432c0d8 100644 --- a/llvm/test/Transforms/InstCombine/memrchr-3.ll +++ b/llvm/test/Transforms/InstCombine/memrchr-3.ll @@ -98,7 +98,7 @@ define ptr @fold_memrchr_ax_c_1(i32 %C) { define ptr @fold_memrchr_a12345_5_5() { ; CHECK-LABEL: @fold_memrchr_a12345_5_5( -; CHECK-NEXT: ret ptr getelementptr inbounds ([5 x i8], ptr @a12345, i64 0, i64 4) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a12345, i64 4) ; %ret = call ptr @memrchr(ptr @a12345, i32 5, i64 5) @@ -122,7 +122,7 @@ define ptr @fold_memrchr_a12345_5_4() { define ptr @fold_memrchr_a12345_4_5() { ; CHECK-LABEL: @fold_memrchr_a12345_4_5( -; CHECK-NEXT: ret ptr getelementptr inbounds ([5 x i8], ptr @a12345, i64 0, i64 3) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a12345, i64 3) ; %ret = call ptr @memrchr(ptr @a12345, i32 4, i64 5) @@ -147,7 +147,7 @@ define ptr @fold_memrchr_a12345p1_1_4() { define ptr @fold_memrchr_a12345p1_2_4() { ; CHECK-LABEL: @fold_memrchr_a12345p1_2_4( -; CHECK-NEXT: ret ptr getelementptr inbounds ([5 x i8], ptr @a12345, i64 0, i64 1) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a12345, i64 1) ; %ptr = getelementptr [5 x i8], ptr @a12345, i32 0, i32 1 @@ -160,7 +160,7 @@ define ptr @fold_memrchr_a12345p1_2_4() { define ptr @fold_memrchr_a12345_2_5() { ; CHECK-LABEL: @fold_memrchr_a12345_2_5( -; CHECK-NEXT: ret ptr getelementptr inbounds ([5 x i8], ptr @a12345, i64 0, i64 1) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a12345, i64 1) ; %ret = call ptr @memrchr(ptr @a12345, i32 2, i64 5) @@ -185,7 +185,7 @@ define ptr @fold_memrchr_a12345_0_n(i64 %N) { define ptr @fold_memrchr_a12345_3_n(i64 %n) { ; CHECK-LABEL: @fold_memrchr_a12345_3_n( ; CHECK-NEXT: [[MEMRCHR_CMP:%.*]] = icmp ult i64 [[N:%.*]], 3 -; CHECK-NEXT: [[MEMRCHR_SEL:%.*]] = select i1 [[MEMRCHR_CMP]], ptr null, ptr getelementptr inbounds ([5 x i8], ptr @a12345, i64 0, i64 2) +; CHECK-NEXT: [[MEMRCHR_SEL:%.*]] = select i1 [[MEMRCHR_CMP]], ptr null, ptr getelementptr inbounds (i8, ptr @a12345, i64 2) ; CHECK-NEXT: ret ptr [[MEMRCHR_SEL]] ; @@ -199,7 +199,7 @@ define ptr @fold_memrchr_a12345_3_n(i64 %n) { define ptr @fold_memrchr_a12345_5_n(i64 %n) { ; CHECK-LABEL: @fold_memrchr_a12345_5_n( ; CHECK-NEXT: [[MEMRCHR_CMP:%.*]] = icmp ult i64 [[N:%.*]], 5 -; CHECK-NEXT: [[MEMRCHR_SEL:%.*]] = select i1 [[MEMRCHR_CMP]], ptr null, ptr getelementptr inbounds ([5 x i8], ptr @a12345, i64 0, i64 4) +; CHECK-NEXT: [[MEMRCHR_SEL:%.*]] = select i1 [[MEMRCHR_CMP]], ptr null, ptr getelementptr inbounds (i8, ptr @a12345, i64 4) ; CHECK-NEXT: ret ptr [[MEMRCHR_SEL]] ; @@ -212,7 +212,7 @@ define ptr @fold_memrchr_a12345_5_n(i64 %n) { define ptr @fold_memrchr_a123123_3_5() { ; CHECK-LABEL: @fold_memrchr_a123123_3_5( -; CHECK-NEXT: ret ptr getelementptr inbounds ([6 x i8], ptr @a123123, i64 0, i64 2) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a123123, i64 2) ; %ret = call ptr @memrchr(ptr @a123123, i32 3, i64 5) @@ -224,7 +224,7 @@ define ptr @fold_memrchr_a123123_3_5() { define ptr @fold_memrchr_a123123_3_6() { ; CHECK-LABEL: @fold_memrchr_a123123_3_6( -; CHECK-NEXT: ret ptr getelementptr inbounds ([6 x i8], ptr @a123123, i64 0, i64 5) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a123123, i64 5) ; %ret = call ptr @memrchr(ptr @a123123, i32 3, i64 6) @@ -235,7 +235,7 @@ define ptr @fold_memrchr_a123123_3_6() { define ptr @fold_memrchr_a123123_2_6() { ; CHECK-LABEL: @fold_memrchr_a123123_2_6( -; CHECK-NEXT: ret ptr getelementptr inbounds ([6 x i8], ptr @a123123, i64 0, i64 4) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a123123, i64 4) ; %ret = call ptr @memrchr(ptr @a123123, i32 2, i64 6) @@ -246,7 +246,7 @@ define ptr @fold_memrchr_a123123_2_6() { define ptr @fold_memrchr_a123123_1_6() { ; CHECK-LABEL: @fold_memrchr_a123123_1_6( -; CHECK-NEXT: ret ptr getelementptr inbounds ([6 x i8], ptr @a123123, i64 0, i64 3) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a123123, i64 3) ; %ret = call ptr @memrchr(ptr @a123123, i32 1, i64 6) diff --git a/llvm/test/Transforms/InstCombine/memrchr-4.ll b/llvm/test/Transforms/InstCombine/memrchr-4.ll index 1e57a3b93595..708b4417a7df 100644 --- a/llvm/test/Transforms/InstCombine/memrchr-4.ll +++ b/llvm/test/Transforms/InstCombine/memrchr-4.ll @@ -16,7 +16,7 @@ define ptr @fold_memrchr_a11111_c_5(i32 %C) { ; CHECK-LABEL: @fold_memrchr_a11111_c_5( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 1 -; CHECK-NEXT: [[MEMRCHR_SEL:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds ([5 x i8], ptr @a11111, i64 0, i64 4), ptr null +; CHECK-NEXT: [[MEMRCHR_SEL:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds (i8, ptr @a11111, i64 4), ptr null ; CHECK-NEXT: ret ptr [[MEMRCHR_SEL]] ; @@ -51,7 +51,7 @@ define ptr @fold_memrchr_a1110111_c_3(i32 %C) { ; CHECK-LABEL: @fold_memrchr_a1110111_c_3( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 1 -; CHECK-NEXT: [[MEMRCHR_SEL:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds ([7 x i8], ptr @a1110111, i64 0, i64 2), ptr null +; CHECK-NEXT: [[MEMRCHR_SEL:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds (i8, ptr @a1110111, i64 2), ptr null ; CHECK-NEXT: ret ptr [[MEMRCHR_SEL]] ; diff --git a/llvm/test/Transforms/InstCombine/merging-multiple-stores-into-successor.ll b/llvm/test/Transforms/InstCombine/merging-multiple-stores-into-successor.ll index 9c5bf3cb5a41..fbf58d47a32d 100644 --- a/llvm/test/Transforms/InstCombine/merging-multiple-stores-into-successor.ll +++ b/llvm/test/Transforms/InstCombine/merging-multiple-stores-into-successor.ll @@ -34,9 +34,9 @@ define void @_Z4testv() { ; CHECK-NEXT: store i16 [[I4]], ptr @arr_4, align 2 ; CHECK-NEXT: [[I8:%.*]] = sext i16 [[I4]] to i32 ; CHECK-NEXT: store i32 [[I8]], ptr @arr_3, align 4 -; CHECK-NEXT: store i32 [[STOREMERGE]], ptr getelementptr inbounds ([0 x i32], ptr @arr_2, i64 0, i64 1), align 4 -; CHECK-NEXT: store i16 [[I4]], ptr getelementptr inbounds ([0 x i16], ptr @arr_4, i64 0, i64 1), align 2 -; CHECK-NEXT: store i32 [[I8]], ptr getelementptr inbounds ([8 x i32], ptr @arr_3, i64 0, i64 1), align 4 +; CHECK-NEXT: store i32 [[STOREMERGE]], ptr getelementptr inbounds (i8, ptr @arr_2, i64 4), align 4 +; CHECK-NEXT: store i16 [[I4]], ptr getelementptr inbounds (i8, ptr @arr_4, i64 2), align 2 +; CHECK-NEXT: store i32 [[I8]], ptr getelementptr inbounds (i8, ptr @arr_3, i64 4), align 4 ; CHECK-NEXT: ret void ; bb: diff --git a/llvm/test/Transforms/InstCombine/objsize.ll b/llvm/test/Transforms/InstCombine/objsize.ll index 33c14f44fc5f..9a3391d91bab 100644 --- a/llvm/test/Transforms/InstCombine/objsize.ll +++ b/llvm/test/Transforms/InstCombine/objsize.ll @@ -64,7 +64,7 @@ define i1 @baz() nounwind { define void @test1(ptr %q, i32 %x) nounwind noinline { ; CHECK-LABEL: @test1( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.objectsize.i32.p0(ptr getelementptr inbounds ([0 x i8], ptr @window, i32 0, i32 10), i1 false, i1 false, i1 false) +; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.objectsize.i32.p0(ptr getelementptr inbounds (i8, ptr @window, i32 10), i1 false, i1 false, i1 false) ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], -1 ; CHECK-NEXT: br i1 [[TMP1]], label %"47", label %"46" ; CHECK: "46": @@ -112,7 +112,7 @@ define void @test3(i1 %c1, ptr %ptr1, ptr %ptr2, ptr %ptr3) nounwind { ; CHECK: bb11: ; CHECK-NEXT: unreachable ; CHECK: bb12: -; CHECK-NEXT: [[TMP0:%.*]] = call ptr @__inline_memcpy_chk(ptr nonnull getelementptr inbounds ([480 x float], ptr @array, i32 0, i32 1), ptr [[PTR3:%.*]], i32 512) #[[ATTR3:[0-9]+]] +; CHECK-NEXT: [[TMP0:%.*]] = call ptr @__inline_memcpy_chk(ptr nonnull getelementptr inbounds (i8, ptr @array, i32 4), ptr [[PTR3:%.*]], i32 512) #[[ATTR3:[0-9]+]] ; CHECK-NEXT: unreachable ; entry: diff --git a/llvm/test/Transforms/InstCombine/pr25342.ll b/llvm/test/Transforms/InstCombine/pr25342.ll index 2f85f99c4ce0..271d69b141dd 100644 --- a/llvm/test/Transforms/InstCombine/pr25342.ll +++ b/llvm/test/Transforms/InstCombine/pr25342.ll @@ -17,9 +17,9 @@ define void @_Z3fooi(i32 signext %n) { ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[TMP2:%.*]] = load float, ptr @dd, align 4 -; CHECK-NEXT: [[TMP3:%.*]] = load float, ptr getelementptr inbounds (%"struct.std::complex", ptr @dd, i64 0, i32 0, i32 1), align 4 +; CHECK-NEXT: [[TMP3:%.*]] = load float, ptr getelementptr inbounds (i8, ptr @dd, i64 4), align 4 ; CHECK-NEXT: [[TMP4:%.*]] = load float, ptr @dd2, align 4 -; CHECK-NEXT: [[TMP5:%.*]] = load float, ptr getelementptr inbounds (%"struct.std::complex", ptr @dd2, i64 0, i32 0, i32 1), align 4 +; CHECK-NEXT: [[TMP5:%.*]] = load float, ptr getelementptr inbounds (i8, ptr @dd2, i64 4), align 4 ; CHECK-NEXT: [[MUL_I:%.*]] = fmul float [[TMP2]], [[TMP4]] ; CHECK-NEXT: [[MUL4_I:%.*]] = fmul float [[TMP3]], [[TMP5]] ; CHECK-NEXT: [[SUB_I:%.*]] = fsub float [[MUL_I]], [[MUL4_I]] @@ -32,7 +32,7 @@ define void @_Z3fooi(i32 signext %n) { ; CHECK-NEXT: br label [[FOR_COND]] ; CHECK: for.end: ; CHECK-NEXT: store float [[TMP0]], ptr @dd, align 4 -; CHECK-NEXT: store float [[TMP1]], ptr getelementptr inbounds (%"struct.std::complex", ptr @dd, i64 0, i32 0, i32 1), align 4 +; CHECK-NEXT: store float [[TMP1]], ptr getelementptr inbounds (i8, ptr @dd, i64 4), align 4 ; CHECK-NEXT: ret void ; entry: @@ -84,9 +84,9 @@ define void @multi_phi(i32 signext %n) { ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr @dd, align 4 -; CHECK-NEXT: [[TMP2:%.*]] = load float, ptr getelementptr inbounds (%"struct.std::complex", ptr @dd, i64 0, i32 0, i32 1), align 4 +; CHECK-NEXT: [[TMP2:%.*]] = load float, ptr getelementptr inbounds (i8, ptr @dd, i64 4), align 4 ; CHECK-NEXT: [[TMP3:%.*]] = load float, ptr @dd2, align 4 -; CHECK-NEXT: [[TMP4:%.*]] = load float, ptr getelementptr inbounds (%"struct.std::complex", ptr @dd2, i64 0, i32 0, i32 1), align 4 +; CHECK-NEXT: [[TMP4:%.*]] = load float, ptr getelementptr inbounds (i8, ptr @dd2, i64 4), align 4 ; CHECK-NEXT: [[MUL_I:%.*]] = fmul float [[TMP1]], [[TMP3]] ; CHECK-NEXT: [[MUL4_I:%.*]] = fmul float [[TMP2]], [[TMP4]] ; CHECK-NEXT: [[SUB_I:%.*]] = fsub float [[MUL_I]], [[MUL4_I]] diff --git a/llvm/test/Transforms/InstCombine/pr33453.ll b/llvm/test/Transforms/InstCombine/pr33453.ll index 45f87b753006..23a232dd0b9a 100644 --- a/llvm/test/Transforms/InstCombine/pr33453.ll +++ b/llvm/test/Transforms/InstCombine/pr33453.ll @@ -6,7 +6,7 @@ define float @patatino() { ; CHECK-LABEL: @patatino( -; CHECK-NEXT: [[FMUL:%.*]] = uitofp i1 mul (i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1)) to float +; CHECK-NEXT: [[FMUL:%.*]] = uitofp i1 mul (i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1)) to float ; CHECK-NEXT: ret float [[FMUL]] ; %uitofp1 = uitofp i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1) to float diff --git a/llvm/test/Transforms/InstCombine/pr38984-inseltpoison.ll b/llvm/test/Transforms/InstCombine/pr38984-inseltpoison.ll index 6613514c7754..92f55b211b63 100644 --- a/llvm/test/Transforms/InstCombine/pr38984-inseltpoison.ll +++ b/llvm/test/Transforms/InstCombine/pr38984-inseltpoison.ll @@ -26,7 +26,7 @@ define <4 x i1> @PR38984_2() { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr @offsets, align 2 ; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i16> poison, i16 [[TMP0]], i64 3 -; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i16, ptr getelementptr inbounds ([21 x i16], ptr @a, i16 1, i16 0), <4 x i16> [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i16, ptr getelementptr inbounds (i8, ptr @a, i16 42), <4 x i16> [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i16, ptr null, <4 x i16> [[TMP1]] ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq <4 x ptr> [[TMP2]], [[TMP3]] ; CHECK-NEXT: ret <4 x i1> [[TMP4]] diff --git a/llvm/test/Transforms/InstCombine/pr38984.ll b/llvm/test/Transforms/InstCombine/pr38984.ll index c148765fce59..a7eddcfbe084 100644 --- a/llvm/test/Transforms/InstCombine/pr38984.ll +++ b/llvm/test/Transforms/InstCombine/pr38984.ll @@ -26,7 +26,7 @@ define <4 x i1> @PR38984_2() { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr @offsets, align 2 ; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i16> , i16 [[TMP0]], i64 3 -; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i16, ptr getelementptr inbounds ([21 x i16], ptr @a, i16 1, i16 0), <4 x i16> [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i16, ptr getelementptr inbounds (i8, ptr @a, i16 42), <4 x i16> [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i16, ptr null, <4 x i16> [[TMP1]] ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq <4 x ptr> [[TMP2]], [[TMP3]] ; CHECK-NEXT: ret <4 x i1> [[TMP4]] diff --git a/llvm/test/Transforms/InstCombine/pr83947.ll b/llvm/test/Transforms/InstCombine/pr83947.ll index c1d601ff6371..63a242abc925 100644 --- a/llvm/test/Transforms/InstCombine/pr83947.ll +++ b/llvm/test/Transforms/InstCombine/pr83947.ll @@ -6,7 +6,7 @@ define void @masked_scatter1() { ; CHECK-LABEL: define void @masked_scatter1() { -; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0( zeroinitializer, shufflevector ( insertelement ( poison, ptr @c, i64 0), poison, zeroinitializer), i32 4, shufflevector ( insertelement ( poison, i1 icmp eq (ptr getelementptr inbounds (i32, ptr @b, i64 1), ptr @c), i64 0), poison, zeroinitializer)) +; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0( zeroinitializer, shufflevector ( insertelement ( poison, ptr @c, i64 0), poison, zeroinitializer), i32 4, shufflevector ( insertelement ( poison, i1 icmp eq (ptr getelementptr inbounds (i8, ptr @b, i64 4), ptr @c), i64 0), poison, zeroinitializer)) ; CHECK-NEXT: ret void ; call void @llvm.masked.scatter.nxv4i32.nxv4p0( zeroinitializer, splat (ptr @c), i32 4, splat (i1 icmp eq (ptr getelementptr (i32, ptr @b, i64 1), ptr @c))) @@ -59,7 +59,7 @@ define void @masked_scatter6() { define void @masked_scatter7() { ; CHECK-LABEL: define void @masked_scatter7() { -; CHECK-NEXT: call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> zeroinitializer, <2 x ptr> , i32 4, <2 x i1> ) +; CHECK-NEXT: call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> zeroinitializer, <2 x ptr> , i32 4, <2 x i1> ) ; CHECK-NEXT: ret void ; call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> zeroinitializer, <2 x ptr> splat (ptr @c), i32 4, <2 x i1> splat (i1 icmp eq (ptr getelementptr (i32, ptr @b, i64 1), ptr @c))) diff --git a/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll b/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll index c783b101251d..7c65a93a0043 100644 --- a/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll +++ b/llvm/test/Transforms/InstCombine/ptr-replace-alloca.ll @@ -15,7 +15,7 @@ define i8 @remove_alloca_use_arg(i1 %cond) { ; CHECK: else: ; CHECK-NEXT: br label [[SINK]] ; CHECK: sink: -; CHECK-NEXT: [[PTR1:%.*]] = phi ptr [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 2), [[IF]] ], [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 1), [[ELSE]] ] +; CHECK-NEXT: [[PTR1:%.*]] = phi ptr [ getelementptr inbounds (i8, ptr @g1, i64 2), [[IF]] ], [ getelementptr inbounds (i8, ptr @g1, i64 1), [[ELSE]] ] ; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[PTR1]], align 1 ; CHECK-NEXT: ret i8 [[LOAD]] ; @@ -114,7 +114,7 @@ define i8 @loop_phi_remove_alloca(i1 %cond) { ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[BB_0:%.*]] ; CHECK: bb.0: -; CHECK-NEXT: [[PTR1:%.*]] = phi ptr [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 1), [[ENTRY:%.*]] ], [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 2), [[BB_1:%.*]] ] +; CHECK-NEXT: [[PTR1:%.*]] = phi ptr [ getelementptr inbounds (i8, ptr @g1, i64 1), [[ENTRY:%.*]] ], [ getelementptr inbounds (i8, ptr @g1, i64 2), [[BB_1:%.*]] ] ; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB_1]], label [[EXIT:%.*]] ; CHECK: bb.1: ; CHECK-NEXT: br label [[BB_0]] @@ -171,7 +171,7 @@ define i8 @loop_phi_late_memtransfer_remove_alloca(i1 %cond) { ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[BB_0:%.*]] ; CHECK: bb.0: -; CHECK-NEXT: [[PTR1:%.*]] = phi ptr [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 1), [[ENTRY:%.*]] ], [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 2), [[BB_1:%.*]] ] +; CHECK-NEXT: [[PTR1:%.*]] = phi ptr [ getelementptr inbounds (i8, ptr @g1, i64 1), [[ENTRY:%.*]] ], [ getelementptr inbounds (i8, ptr @g1, i64 2), [[BB_1:%.*]] ] ; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB_1]], label [[EXIT:%.*]] ; CHECK: bb.1: ; CHECK-NEXT: br label [[BB_0]] @@ -288,7 +288,7 @@ define i32 @addrspace_diff_remove_alloca(i1 %cond) { ; CHECK: if: ; CHECK-NEXT: br label [[JOIN]] ; CHECK: join: -; CHECK-NEXT: [[PHI1:%.*]] = phi ptr addrspace(1) [ @g2, [[IF]] ], [ getelementptr inbounds ([32 x i8], ptr addrspace(1) @g2, i64 0, i64 2), [[ENTRY:%.*]] ] +; CHECK-NEXT: [[PHI1:%.*]] = phi ptr addrspace(1) [ @g2, [[IF]] ], [ getelementptr inbounds (i8, ptr addrspace(1) @g2, i64 2), [[ENTRY:%.*]] ] ; CHECK-NEXT: [[V:%.*]] = load i32, ptr addrspace(1) [[PHI1]], align 4 ; CHECK-NEXT: ret i32 [[V]] ; diff --git a/llvm/test/Transforms/InstCombine/rem.ll b/llvm/test/Transforms/InstCombine/rem.ll index ae390e72a4b7..a8fa72c37d32 100644 --- a/llvm/test/Transforms/InstCombine/rem.ll +++ b/llvm/test/Transforms/InstCombine/rem.ll @@ -522,7 +522,7 @@ define i32 @pr27968_0(i1 %c0, ptr %p) { ; CHECK-NEXT: [[V:%.*]] = load volatile i32, ptr [[P:%.*]], align 4 ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: -; CHECK-NEXT: br i1 icmp eq (ptr getelementptr inbounds ([5 x i16], ptr @a, i64 0, i64 4), ptr @b), label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] +; CHECK-NEXT: br i1 icmp eq (ptr getelementptr inbounds (i8, ptr @a, i64 8), ptr @b), label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] ; CHECK: rem.is.safe: ; CHECK-NEXT: ret i32 0 ; CHECK: rem.is.unsafe: @@ -591,7 +591,7 @@ define i32 @pr27968_2(i1 %c0, ptr %p) { ; CHECK-NEXT: [[V:%.*]] = load volatile i32, ptr [[P:%.*]], align 4 ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: -; CHECK-NEXT: br i1 icmp eq (ptr getelementptr inbounds ([5 x i16], ptr @a, i64 0, i64 4), ptr @b), label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] +; CHECK-NEXT: br i1 icmp eq (ptr getelementptr inbounds (i8, ptr @a, i64 8), ptr @b), label [[REM_IS_SAFE:%.*]], label [[REM_IS_UNSAFE:%.*]] ; CHECK: rem.is.safe: ; CHECK-NEXT: ret i32 0 ; CHECK: rem.is.unsafe: diff --git a/llvm/test/Transforms/InstCombine/select-and-or.ll b/llvm/test/Transforms/InstCombine/select-and-or.ll index 0f7acd4d56c0..0965e1c8348e 100644 --- a/llvm/test/Transforms/InstCombine/select-and-or.ll +++ b/llvm/test/Transforms/InstCombine/select-and-or.ll @@ -431,7 +431,7 @@ define i1 @not_false_not_use3(i1 %x, i1 %y) { define i1 @demorgan_select_infloop1(i1 %L) { ; CHECK-LABEL: @demorgan_select_infloop1( ; CHECK-NEXT: [[NOT_L:%.*]] = xor i1 [[L:%.*]], true -; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 xor (i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1)), i1 false +; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 xor (i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1)), i1 false ; CHECK-NEXT: ret i1 [[C15]] ; %not.L = xor i1 %L, true @@ -443,7 +443,7 @@ define i1 @demorgan_select_infloop1(i1 %L) { define i1 @demorgan_select_infloop2(i1 %L) { ; CHECK-LABEL: @demorgan_select_infloop2( ; CHECK-NEXT: [[NOT_L:%.*]] = xor i1 [[L:%.*]], true -; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 true, i1 xor (i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i16, ptr @g2, i64 1), ptr @g1)) +; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 true, i1 xor (i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1), i1 icmp eq (ptr getelementptr inbounds (i8, ptr @g2, i64 2), ptr @g1)) ; CHECK-NEXT: ret i1 [[C15]] ; %not.L = xor i1 %L, true diff --git a/llvm/test/Transforms/InstCombine/simplify-libcalls-i16.ll b/llvm/test/Transforms/InstCombine/simplify-libcalls-i16.ll index 2ac9e2996c4f..9a08b6b5cf9f 100644 --- a/llvm/test/Transforms/InstCombine/simplify-libcalls-i16.ll +++ b/llvm/test/Transforms/InstCombine/simplify-libcalls-i16.ll @@ -29,11 +29,11 @@ define void @foo(ptr %P, ptr %X) { define ptr @test1() { ; CHECK32-LABEL: @test1( -; CHECK32-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds ([5 x i8], ptr @str, i32 0, i32 2), i16 103) +; CHECK32-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds (i8, ptr @str, i32 2), i16 103) ; CHECK32-NEXT: ret ptr [[TMP3]] ; ; CHECK16-LABEL: @test1( -; CHECK16-NEXT: ret ptr getelementptr inbounds ([5 x i8], ptr @str, i32 0, i32 3) +; CHECK16-NEXT: ret ptr getelementptr inbounds (i8, ptr @str, i32 3) ; %tmp3 = tail call ptr @strchr( ptr getelementptr ([5 x i8], ptr @str, i32 0, i16 2), i16 103 ) ; [#uses=1] ret ptr %tmp3 @@ -45,11 +45,11 @@ declare ptr @strchr(ptr, i16) define ptr @test2() { ; CHECK32-LABEL: @test2( -; CHECK32-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds ([8 x i8], ptr @str1, i32 0, i32 2), i16 0) +; CHECK32-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds (i8, ptr @str1, i32 2), i16 0) ; CHECK32-NEXT: ret ptr [[TMP3]] ; ; CHECK16-LABEL: @test2( -; CHECK16-NEXT: ret ptr getelementptr inbounds ([8 x i8], ptr @str1, i32 0, i32 7) +; CHECK16-NEXT: ret ptr getelementptr inbounds (i8, ptr @str1, i32 7) ; %tmp3 = tail call ptr @strchr( ptr getelementptr ([8 x i8], ptr @str1, i32 0, i32 2), i16 0 ) ; [#uses=1] ret ptr %tmp3 @@ -58,7 +58,7 @@ define ptr @test2() { define ptr @test3() { ; CHECK32-LABEL: @test3( ; CHECK32-NEXT: entry: -; CHECK32-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds ([5 x i8], ptr @str2, i32 0, i32 1), i16 80) +; CHECK32-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds (i8, ptr @str2, i32 1), i16 80) ; CHECK32-NEXT: ret ptr [[TMP3]] ; ; CHECK16-LABEL: @test3( diff --git a/llvm/test/Transforms/InstCombine/simplify-libcalls.ll b/llvm/test/Transforms/InstCombine/simplify-libcalls.ll index 5ebb497ee765..bb2728a103ec 100644 --- a/llvm/test/Transforms/InstCombine/simplify-libcalls.ll +++ b/llvm/test/Transforms/InstCombine/simplify-libcalls.ll @@ -29,10 +29,10 @@ define void @foo(ptr %P, ptr %X) { define ptr @test1() { ; CHECK32-LABEL: @test1( -; CHECK32-NEXT: ret ptr getelementptr inbounds ([5 x i8], ptr @str, i32 0, i32 3) +; CHECK32-NEXT: ret ptr getelementptr inbounds (i8, ptr @str, i32 3) ; ; CHECK16-LABEL: @test1( -; CHECK16-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds ([5 x i8], ptr @str, i32 0, i32 2), i32 103) +; CHECK16-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds (i8, ptr @str, i32 2), i32 103) ; CHECK16-NEXT: ret ptr [[TMP3]] ; %tmp3 = tail call ptr @strchr( ptr getelementptr ([5 x i8], ptr @str, i32 0, i32 2), i32 103 ) ; [#uses=1] @@ -45,10 +45,10 @@ declare ptr @strchr(ptr, i32) define ptr @test2() { ; CHECK32-LABEL: @test2( -; CHECK32-NEXT: ret ptr getelementptr inbounds ([8 x i8], ptr @str1, i32 0, i32 7) +; CHECK32-NEXT: ret ptr getelementptr inbounds (i8, ptr @str1, i32 7) ; ; CHECK16-LABEL: @test2( -; CHECK16-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds ([8 x i8], ptr @str1, i32 0, i32 2), i32 0) +; CHECK16-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds (i8, ptr @str1, i32 2), i32 0) ; CHECK16-NEXT: ret ptr [[TMP3]] ; %tmp3 = tail call ptr @strchr( ptr getelementptr ([8 x i8], ptr @str1, i32 0, i32 2), i32 0 ) ; [#uses=1] @@ -62,7 +62,7 @@ define ptr @test3() { ; ; CHECK16-LABEL: @test3( ; CHECK16-NEXT: entry: -; CHECK16-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds ([5 x i8], ptr @str2, i32 0, i32 1), i32 80) +; CHECK16-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds (i8, ptr @str2, i32 1), i32 80) ; CHECK16-NEXT: ret ptr [[TMP3]] ; entry: diff --git a/llvm/test/Transforms/InstCombine/snprintf-2.ll b/llvm/test/Transforms/InstCombine/snprintf-2.ll index 46694e0764a0..0465457aacec 100644 --- a/llvm/test/Transforms/InstCombine/snprintf-2.ll +++ b/llvm/test/Transforms/InstCombine/snprintf-2.ll @@ -21,54 +21,54 @@ declare i32 @snprintf(ptr, i64, ptr, ...) define void @fold_snprintf_fmt() { ; BE-LABEL: @fold_snprintf_fmt( -; BE-NEXT: [[PDIMAX:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 2147483647), align 8 +; BE-NEXT: [[PDIMAX:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 17179869176), align 8 ; BE-NEXT: store i32 825373440, ptr [[PDIMAX]], align 1 ; BE-NEXT: store i32 3, ptr @asiz, align 4 -; BE-NEXT: [[PD5:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 5), align 8 +; BE-NEXT: [[PD5:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 40), align 8 ; BE-NEXT: store i32 825373440, ptr [[PD5]], align 1 -; BE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 5), align 4 -; BE-NEXT: [[PD4:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 4), align 8 +; BE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 20), align 4 +; BE-NEXT: [[PD4:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 32), align 8 ; BE-NEXT: store i32 825373440, ptr [[PD4]], align 1 -; BE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 4), align 4 -; BE-NEXT: [[PD3:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 3), align 8 +; BE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 16), align 4 +; BE-NEXT: [[PD3:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 24), align 8 ; BE-NEXT: store i16 12594, ptr [[PD3]], align 1 ; BE-NEXT: [[ENDPTR:%.*]] = getelementptr inbounds i8, ptr [[PD3]], i64 2 ; BE-NEXT: store i8 0, ptr [[ENDPTR]], align 1 -; BE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 3), align 4 -; BE-NEXT: [[PD2:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 2), align 8 +; BE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 12), align 4 +; BE-NEXT: [[PD2:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 16), align 8 ; BE-NEXT: store i8 49, ptr [[PD2]], align 1 ; BE-NEXT: [[ENDPTR1:%.*]] = getelementptr inbounds i8, ptr [[PD2]], i64 1 ; BE-NEXT: store i8 0, ptr [[ENDPTR1]], align 1 -; BE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 2), align 4 -; BE-NEXT: [[PD1:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 1), align 8 +; BE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 8), align 4 +; BE-NEXT: [[PD1:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 8), align 8 ; BE-NEXT: store i8 0, ptr [[PD1]], align 1 -; BE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 1), align 4 +; BE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 4), align 4 ; BE-NEXT: store i32 3, ptr @asiz, align 4 ; BE-NEXT: ret void ; ; LE-LABEL: @fold_snprintf_fmt( -; LE-NEXT: [[PDIMAX:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 2147483647), align 8 +; LE-NEXT: [[PDIMAX:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 17179869176), align 8 ; LE-NEXT: store i32 3355185, ptr [[PDIMAX]], align 1 ; LE-NEXT: store i32 3, ptr @asiz, align 4 -; LE-NEXT: [[PD5:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 5), align 8 +; LE-NEXT: [[PD5:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 40), align 8 ; LE-NEXT: store i32 3355185, ptr [[PD5]], align 1 -; LE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 5), align 4 -; LE-NEXT: [[PD4:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 4), align 8 +; LE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 20), align 4 +; LE-NEXT: [[PD4:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 32), align 8 ; LE-NEXT: store i32 3355185, ptr [[PD4]], align 1 -; LE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 4), align 4 -; LE-NEXT: [[PD3:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 3), align 8 +; LE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 16), align 4 +; LE-NEXT: [[PD3:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 24), align 8 ; LE-NEXT: store i16 12849, ptr [[PD3]], align 1 ; LE-NEXT: [[ENDPTR:%.*]] = getelementptr inbounds i8, ptr [[PD3]], i64 2 ; LE-NEXT: store i8 0, ptr [[ENDPTR]], align 1 -; LE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 3), align 4 -; LE-NEXT: [[PD2:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 2), align 8 +; LE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 12), align 4 +; LE-NEXT: [[PD2:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 16), align 8 ; LE-NEXT: store i8 49, ptr [[PD2]], align 1 ; LE-NEXT: [[ENDPTR1:%.*]] = getelementptr inbounds i8, ptr [[PD2]], i64 1 ; LE-NEXT: store i8 0, ptr [[ENDPTR1]], align 1 -; LE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 2), align 4 -; LE-NEXT: [[PD1:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 1), align 8 +; LE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 8), align 4 +; LE-NEXT: [[PD1:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 8), align 8 ; LE-NEXT: store i8 0, ptr [[PD1]], align 1 -; LE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 1), align 4 +; LE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 4), align 4 ; LE-NEXT: store i32 3, ptr @asiz, align 4 ; LE-NEXT: ret void ; @@ -111,9 +111,9 @@ define void @fold_snprintf_fmt() { define void @call_snprintf_fmt_ximax() { ; ANY-LABEL: @call_snprintf_fmt_ximax( -; ANY-NEXT: [[PDM1:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 1), align 8 +; ANY-NEXT: [[PDM1:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 8), align 8 ; ANY-NEXT: [[NM1:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr noundef nonnull dereferenceable(1) [[PDM1]], i64 -1, ptr nonnull @s) -; ANY-NEXT: store i32 [[NM1]], ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 1), align 4 +; ANY-NEXT: store i32 [[NM1]], ptr getelementptr (i8, ptr @asiz, i64 4), align 4 ; ANY-NEXT: [[PDIMAXP1:%.*]] = load ptr, ptr @adst, align 8 ; ANY-NEXT: [[NIMAXP1:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr noundef nonnull dereferenceable(1) [[PDIMAXP1]], i64 2147483648, ptr nonnull @s) ; ANY-NEXT: store i32 [[NIMAXP1]], ptr @asiz, align 4 diff --git a/llvm/test/Transforms/InstCombine/snprintf-3.ll b/llvm/test/Transforms/InstCombine/snprintf-3.ll index 0332aa71ad64..7c93580b4ea5 100644 --- a/llvm/test/Transforms/InstCombine/snprintf-3.ll +++ b/llvm/test/Transforms/InstCombine/snprintf-3.ll @@ -22,54 +22,54 @@ declare i32 @snprintf(ptr, i64, ptr, ...) define void @fold_snprintf_pcnt_s() { ; BE-LABEL: @fold_snprintf_pcnt_s( -; BE-NEXT: [[PDIMAX:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 2147483647), align 8 +; BE-NEXT: [[PDIMAX:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 17179869176), align 8 ; BE-NEXT: store i32 825373440, ptr [[PDIMAX]], align 1 ; BE-NEXT: store i32 3, ptr @asiz, align 4 -; BE-NEXT: [[PD5:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 5), align 8 +; BE-NEXT: [[PD5:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 40), align 8 ; BE-NEXT: store i32 825373440, ptr [[PD5]], align 1 -; BE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 5), align 4 -; BE-NEXT: [[PD4:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 4), align 8 +; BE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 20), align 4 +; BE-NEXT: [[PD4:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 32), align 8 ; BE-NEXT: store i32 825373440, ptr [[PD4]], align 1 -; BE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 4), align 4 -; BE-NEXT: [[PD3:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 3), align 8 +; BE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 16), align 4 +; BE-NEXT: [[PD3:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 24), align 8 ; BE-NEXT: store i16 12594, ptr [[PD3]], align 1 ; BE-NEXT: [[ENDPTR:%.*]] = getelementptr inbounds i8, ptr [[PD3]], i64 2 ; BE-NEXT: store i8 0, ptr [[ENDPTR]], align 1 -; BE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 3), align 4 -; BE-NEXT: [[PD2:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 2), align 8 +; BE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 12), align 4 +; BE-NEXT: [[PD2:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 16), align 8 ; BE-NEXT: store i8 49, ptr [[PD2]], align 1 ; BE-NEXT: [[ENDPTR1:%.*]] = getelementptr inbounds i8, ptr [[PD2]], i64 1 ; BE-NEXT: store i8 0, ptr [[ENDPTR1]], align 1 -; BE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 2), align 4 -; BE-NEXT: [[PD1:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 1), align 8 +; BE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 8), align 4 +; BE-NEXT: [[PD1:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 8), align 8 ; BE-NEXT: store i8 0, ptr [[PD1]], align 1 -; BE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 1), align 4 +; BE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 4), align 4 ; BE-NEXT: store i32 3, ptr @asiz, align 4 ; BE-NEXT: ret void ; ; LE-LABEL: @fold_snprintf_pcnt_s( -; LE-NEXT: [[PDIMAX:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 2147483647), align 8 +; LE-NEXT: [[PDIMAX:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 17179869176), align 8 ; LE-NEXT: store i32 3355185, ptr [[PDIMAX]], align 1 ; LE-NEXT: store i32 3, ptr @asiz, align 4 -; LE-NEXT: [[PD5:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 5), align 8 +; LE-NEXT: [[PD5:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 40), align 8 ; LE-NEXT: store i32 3355185, ptr [[PD5]], align 1 -; LE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 5), align 4 -; LE-NEXT: [[PD4:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 4), align 8 +; LE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 20), align 4 +; LE-NEXT: [[PD4:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 32), align 8 ; LE-NEXT: store i32 3355185, ptr [[PD4]], align 1 -; LE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 4), align 4 -; LE-NEXT: [[PD3:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 3), align 8 +; LE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 16), align 4 +; LE-NEXT: [[PD3:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 24), align 8 ; LE-NEXT: store i16 12849, ptr [[PD3]], align 1 ; LE-NEXT: [[ENDPTR:%.*]] = getelementptr inbounds i8, ptr [[PD3]], i64 2 ; LE-NEXT: store i8 0, ptr [[ENDPTR]], align 1 -; LE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 3), align 4 -; LE-NEXT: [[PD2:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 2), align 8 +; LE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 12), align 4 +; LE-NEXT: [[PD2:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 16), align 8 ; LE-NEXT: store i8 49, ptr [[PD2]], align 1 ; LE-NEXT: [[ENDPTR1:%.*]] = getelementptr inbounds i8, ptr [[PD2]], i64 1 ; LE-NEXT: store i8 0, ptr [[ENDPTR1]], align 1 -; LE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 2), align 4 -; LE-NEXT: [[PD1:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 1), align 8 +; LE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 8), align 4 +; LE-NEXT: [[PD1:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 8), align 8 ; LE-NEXT: store i8 0, ptr [[PD1]], align 1 -; LE-NEXT: store i32 3, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 1), align 4 +; LE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 4), align 4 ; LE-NEXT: store i32 3, ptr @asiz, align 4 ; LE-NEXT: ret void ; @@ -112,9 +112,9 @@ define void @fold_snprintf_pcnt_s() { define void @call_snprintf_pcnt_s_ximax() { ; ANY-LABEL: @call_snprintf_pcnt_s_ximax( -; ANY-NEXT: [[PDM1:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 1), align 8 +; ANY-NEXT: [[PDM1:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 8), align 8 ; ANY-NEXT: [[NM1:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr noundef nonnull dereferenceable(1) [[PDM1]], i64 -1, ptr nonnull @pcnt_s, ptr nonnull @s) -; ANY-NEXT: store i32 [[NM1]], ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 1), align 4 +; ANY-NEXT: store i32 [[NM1]], ptr getelementptr (i8, ptr @asiz, i64 4), align 4 ; ANY-NEXT: [[PDIMAXP1:%.*]] = load ptr, ptr @adst, align 8 ; ANY-NEXT: [[NIMAXP1:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr noundef nonnull dereferenceable(1) [[PDIMAXP1]], i64 2147483648, ptr nonnull @pcnt_s, ptr nonnull @s) ; ANY-NEXT: store i32 [[NIMAXP1]], ptr @asiz, align 4 diff --git a/llvm/test/Transforms/InstCombine/snprintf-4.ll b/llvm/test/Transforms/InstCombine/snprintf-4.ll index 4536a6d8817e..7006838ae9b5 100644 --- a/llvm/test/Transforms/InstCombine/snprintf-4.ll +++ b/llvm/test/Transforms/InstCombine/snprintf-4.ll @@ -24,29 +24,29 @@ define void @fold_snprintf_pcnt_c(i32 %c) { ; CHECK-NEXT: [[NUL:%.*]] = getelementptr inbounds i8, ptr [[PDIMAX]], i64 1 ; CHECK-NEXT: store i8 0, ptr [[NUL]], align 1 ; CHECK-NEXT: store i32 1, ptr @asiz, align 4 -; CHECK-NEXT: [[PD2:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 1), align 8 +; CHECK-NEXT: [[PD2:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 8), align 8 ; CHECK-NEXT: store i8 2, ptr [[PD2]], align 1 ; CHECK-NEXT: [[NUL1:%.*]] = getelementptr inbounds i8, ptr [[PD2]], i64 1 ; CHECK-NEXT: store i8 0, ptr [[NUL1]], align 1 -; CHECK-NEXT: store i32 1, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 1), align 4 -; CHECK-NEXT: [[PD2_0:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 2), align 8 +; CHECK-NEXT: store i32 1, ptr getelementptr (i8, ptr @asiz, i64 4), align 4 +; CHECK-NEXT: [[PD2_0:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 16), align 8 ; CHECK-NEXT: store i8 0, ptr [[PD2_0]], align 1 ; CHECK-NEXT: [[NUL2:%.*]] = getelementptr inbounds i8, ptr [[PD2_0]], i64 1 ; CHECK-NEXT: store i8 0, ptr [[NUL2]], align 1 -; CHECK-NEXT: store i32 1, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 2), align 4 -; CHECK-NEXT: [[PD1:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 3), align 8 +; CHECK-NEXT: store i32 1, ptr getelementptr (i8, ptr @asiz, i64 8), align 4 +; CHECK-NEXT: [[PD1:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 24), align 8 ; CHECK-NEXT: store i8 0, ptr [[PD1]], align 1 -; CHECK-NEXT: store i32 1, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 3), align 4 -; CHECK-NEXT: store i32 1, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 4), align 4 -; CHECK-NEXT: [[PD2_C:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 4), align 8 +; CHECK-NEXT: store i32 1, ptr getelementptr (i8, ptr @asiz, i64 12), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr (i8, ptr @asiz, i64 16), align 4 +; CHECK-NEXT: [[PD2_C:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 32), align 8 ; CHECK-NEXT: [[CHAR:%.*]] = trunc i32 [[C:%.*]] to i8 ; CHECK-NEXT: store i8 [[CHAR]], ptr [[PD2_C]], align 1 ; CHECK-NEXT: [[NUL3:%.*]] = getelementptr inbounds i8, ptr [[PD2_C]], i64 1 ; CHECK-NEXT: store i8 0, ptr [[NUL3]], align 1 -; CHECK-NEXT: store i32 1, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 4), align 4 -; CHECK-NEXT: [[PD1_C:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 5), align 8 +; CHECK-NEXT: store i32 1, ptr getelementptr (i8, ptr @asiz, i64 16), align 4 +; CHECK-NEXT: [[PD1_C:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 40), align 8 ; CHECK-NEXT: store i8 0, ptr [[PD1_C]], align 1 -; CHECK-NEXT: store i32 1, ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 5), align 4 +; CHECK-NEXT: store i32 1, ptr getelementptr (i8, ptr @asiz, i64 20), align 4 ; CHECK-NEXT: ret void ; @@ -100,12 +100,12 @@ define void @call_snprintf_pcnt_c_ximax(i32 %c) { ; CHECK-NEXT: [[PDM1:%.*]] = load ptr, ptr @adst, align 8 ; CHECK-NEXT: [[NM1:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr noundef nonnull dereferenceable(1) [[PDM1]], i64 -1, ptr nonnull @pcnt_c, i8 0) ; CHECK-NEXT: store i32 [[NM1]], ptr @asiz, align 4 -; CHECK-NEXT: [[PDIMAXP1:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 1), align 8 +; CHECK-NEXT: [[PDIMAXP1:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 8), align 8 ; CHECK-NEXT: [[NIMAXP1:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr noundef nonnull dereferenceable(1) [[PDIMAXP1]], i64 2147483648, ptr nonnull @pcnt_c, i8 1) -; CHECK-NEXT: store i32 [[NIMAXP1]], ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 1), align 4 -; CHECK-NEXT: [[PDM1SL32:%.*]] = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i64 0, i64 2), align 8 +; CHECK-NEXT: store i32 [[NIMAXP1]], ptr getelementptr (i8, ptr @asiz, i64 4), align 4 +; CHECK-NEXT: [[PDM1SL32:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 16), align 8 ; CHECK-NEXT: [[NM1SL32:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr noundef nonnull dereferenceable(1) [[PDM1SL32]], i64 -4294967296, ptr nonnull @pcnt_c, i8 1) -; CHECK-NEXT: store i32 [[NM1SL32]], ptr getelementptr ([0 x i32], ptr @asiz, i64 0, i64 2), align 4 +; CHECK-NEXT: store i32 [[NM1SL32]], ptr getelementptr (i8, ptr @asiz, i64 8), align 4 ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/InstCombine/stpcpy-1.ll b/llvm/test/Transforms/InstCombine/stpcpy-1.ll index 86691a08a798..2ddacb209744 100644 --- a/llvm/test/Transforms/InstCombine/stpcpy-1.ll +++ b/llvm/test/Transforms/InstCombine/stpcpy-1.ll @@ -16,7 +16,7 @@ declare ptr @stpcpy(ptr, ptr) define ptr @test_simplify1() { ; CHECK-LABEL: @test_simplify1( ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(6) @a, ptr noundef nonnull align 1 dereferenceable(6) @hello, i32 6, i1 false) -; CHECK-NEXT: ret ptr getelementptr inbounds ([32 x i8], ptr @a, i32 0, i32 5) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a, i32 5) ; %ret = call ptr @stpcpy(ptr @a, ptr @hello) ret ptr %ret @@ -62,7 +62,7 @@ define ptr @test_no_simplify2(ptr %dst, ptr %src) { define ptr @test_no_incompatible_attr() { ; CHECK-LABEL: @test_no_incompatible_attr( ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(6) @a, ptr noundef nonnull align 1 dereferenceable(6) @hello, i32 6, i1 false) -; CHECK-NEXT: ret ptr getelementptr inbounds ([32 x i8], ptr @a, i32 0, i32 5) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a, i32 5) ; %ret = call dereferenceable(1) ptr @stpcpy(ptr @a, ptr @hello) ret ptr %ret diff --git a/llvm/test/Transforms/InstCombine/stpcpy_chk-1.ll b/llvm/test/Transforms/InstCombine/stpcpy_chk-1.ll index 5ebd9fae7620..2d775f35c8bd 100644 --- a/llvm/test/Transforms/InstCombine/stpcpy_chk-1.ll +++ b/llvm/test/Transforms/InstCombine/stpcpy_chk-1.ll @@ -15,7 +15,7 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3 define ptr @test_simplify1() { ; CHECK-LABEL: @test_simplify1( ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(12) @a, ptr noundef nonnull align 1 dereferenceable(12) @.str, i32 12, i1 false) -; CHECK-NEXT: ret ptr getelementptr inbounds ([60 x i8], ptr @a, i32 0, i32 11) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a, i32 11) ; %ret = call ptr @__stpcpy_chk(ptr @a, ptr @.str, i32 60) @@ -25,7 +25,7 @@ define ptr @test_simplify1() { define ptr @test_simplify2() { ; CHECK-LABEL: @test_simplify2( ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(12) @a, ptr noundef nonnull align 1 dereferenceable(12) @.str, i32 12, i1 false) -; CHECK-NEXT: ret ptr getelementptr inbounds ([60 x i8], ptr @a, i32 0, i32 11) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a, i32 11) ; %ret = call ptr @__stpcpy_chk(ptr @a, ptr @.str, i32 12) @@ -35,7 +35,7 @@ define ptr @test_simplify2() { define ptr @test_simplify3() { ; CHECK-LABEL: @test_simplify3( ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(12) @a, ptr noundef nonnull align 1 dereferenceable(12) @.str, i32 12, i1 false) -; CHECK-NEXT: ret ptr getelementptr inbounds ([60 x i8], ptr @a, i32 0, i32 11) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a, i32 11) ; %ret = call ptr @__stpcpy_chk(ptr @a, ptr @.str, i32 -1) @@ -45,7 +45,7 @@ define ptr @test_simplify3() { define ptr @test_simplify1_tail() { ; CHECK-LABEL: @test_simplify1_tail( ; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(12) @a, ptr noundef nonnull align 1 dereferenceable(12) @.str, i32 12, i1 false) -; CHECK-NEXT: ret ptr getelementptr inbounds ([60 x i8], ptr @a, i32 0, i32 11) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a, i32 11) ; %ret = tail call ptr @__stpcpy_chk(ptr @a, ptr @.str, i32 60) @@ -80,7 +80,7 @@ define ptr @test_simplify5() { ; CHECK-LABEL: @test_simplify5( ; CHECK-NEXT: [[LEN:%.*]] = call i32 @llvm.objectsize.i32.p0(ptr @a, i1 false, i1 false, i1 false) ; CHECK-NEXT: [[TMP1:%.*]] = call ptr @__memcpy_chk(ptr nonnull @a, ptr nonnull @.str, i32 12, i32 [[LEN]]) -; CHECK-NEXT: ret ptr getelementptr inbounds ([60 x i8], ptr @a, i32 0, i32 11) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a, i32 11) ; %len = call i32 @llvm.objectsize.i32.p0(ptr @a, i1 false, i1 false, i1 false) diff --git a/llvm/test/Transforms/InstCombine/stpncpy-1.ll b/llvm/test/Transforms/InstCombine/stpncpy-1.ll index 15eee6c10193..0a4caa2c05f9 100644 --- a/llvm/test/Transforms/InstCombine/stpncpy-1.ll +++ b/llvm/test/Transforms/InstCombine/stpncpy-1.ll @@ -28,18 +28,18 @@ declare void @sink(ptr, ptr) ; to D + strnlen(D, N) or, equivalently, D + (*D != '\0'), when N < 2. ;. -; ANY: @[[A4:[a-zA-Z0-9_$"\\.-]+]] = constant [4 x i8] c"1234" -; ANY: @[[S4:[a-zA-Z0-9_$"\\.-]+]] = constant [5 x i8] c"1234\00" -; ANY: @[[STR:[a-zA-Z0-9_$"\\.-]+]] = private constant [4 x i8] c"4\00\00\00" -; ANY: @[[STR_1:[a-zA-Z0-9_$"\\.-]+]] = private constant [10 x i8] c"4\00\00\00\00\00\00\00\00\00" -; ANY: @[[STR_2:[a-zA-Z0-9_$"\\.-]+]] = private constant [10 x i8] c"1234\00\00\00\00\00\00" -; ANY: @[[STR_3:[a-zA-Z0-9_$"\\.-]+]] = private unnamed_addr constant [4 x i8] c"4\00\00\00", align 1 -; ANY: @[[STR_4:[a-zA-Z0-9_$"\\.-]+]] = private unnamed_addr constant [10 x i8] c"4\00\00\00\00\00\00\00\00\00", align 1 -; ANY: @[[STR_5:[a-zA-Z0-9_$"\\.-]+]] = private unnamed_addr constant [10 x i8] c"1234\00\00\00\00\00\00", align 1 -; ANY: @[[STR_6:[a-zA-Z0-9_$"\\.-]+]] = private unnamed_addr constant [4 x i8] c"4\00\00\00", align 1 -; ANY: @[[STR_7:[a-zA-Z0-9_$"\\.-]+]] = private unnamed_addr constant [10 x i8] c"4\00\00\00\00\00\00\00\00\00", align 1 -; ANY: @[[STR_8:[a-zA-Z0-9_$"\\.-]+]] = private unnamed_addr constant [10 x i8] c"1234\00\00\00\00\00\00", align 1 -; ANY: @[[STR_9:[a-zA-Z0-9_$"\\.-]+]] = private unnamed_addr constant [10 x i8] c"1234\00\00\00\00\00\00", align 1 +; ANY: @a4 = constant [4 x i8] c"1234" +; ANY: @s4 = constant [5 x i8] c"1234\00" +; ANY: @str = private constant [4 x i8] c"4\00\00\00" +; ANY: @str.1 = private constant [10 x i8] c"4\00\00\00\00\00\00\00\00\00" +; ANY: @str.2 = private constant [10 x i8] c"1234\00\00\00\00\00\00" +; ANY: @str.3 = private unnamed_addr constant [4 x i8] c"4\00\00\00", align 1 +; ANY: @str.4 = private unnamed_addr constant [10 x i8] c"4\00\00\00\00\00\00\00\00\00", align 1 +; ANY: @str.5 = private unnamed_addr constant [10 x i8] c"1234\00\00\00\00\00\00", align 1 +; ANY: @str.6 = private unnamed_addr constant [4 x i8] c"4\00\00\00", align 1 +; ANY: @str.7 = private unnamed_addr constant [10 x i8] c"4\00\00\00\00\00\00\00\00\00", align 1 +; ANY: @str.8 = private unnamed_addr constant [10 x i8] c"1234\00\00\00\00\00\00", align 1 +; ANY: @str.9 = private unnamed_addr constant [10 x i8] c"1234\00\00\00\00\00\00", align 1 ;. define void @fold_stpncpy_overlap(ptr %dst, i64 %n) { ; ANY-LABEL: @fold_stpncpy_overlap( @@ -273,11 +273,11 @@ define void @fold_stpncpy_s4(ptr %dst, i64 %n) { define void @call_stpncpy_xx_n(ptr %dst, i64 %n) { ; ANY-LABEL: @call_stpncpy_xx_n( -; ANY-NEXT: [[EA1_N:%.*]] = call ptr @stpncpy(ptr [[DST:%.*]], ptr nonnull dereferenceable(2) getelementptr inbounds ([4 x i8], ptr @a4, i64 0, i64 3), i64 [[N:%.*]]) +; ANY-NEXT: [[EA1_N:%.*]] = call ptr @stpncpy(ptr [[DST:%.*]], ptr nonnull dereferenceable(2) getelementptr inbounds (i8, ptr @a4, i64 3), i64 [[N:%.*]]) ; ANY-NEXT: call void @sink(ptr [[DST]], ptr [[EA1_N]]) ; ANY-NEXT: [[EA4_N:%.*]] = call ptr @stpncpy(ptr [[DST]], ptr nonnull dereferenceable(5) @a4, i64 [[N]]) ; ANY-NEXT: call void @sink(ptr [[DST]], ptr [[EA4_N]]) -; ANY-NEXT: [[ES1_N:%.*]] = call ptr @stpncpy(ptr [[DST]], ptr nonnull dereferenceable(2) getelementptr inbounds ([5 x i8], ptr @s4, i64 0, i64 3), i64 [[N]]) +; ANY-NEXT: [[ES1_N:%.*]] = call ptr @stpncpy(ptr [[DST]], ptr nonnull dereferenceable(2) getelementptr inbounds (i8, ptr @s4, i64 3), i64 [[N]]) ; ANY-NEXT: call void @sink(ptr [[DST]], ptr [[ES1_N]]) ; ANY-NEXT: [[ES4_N:%.*]] = call ptr @stpncpy(ptr [[DST]], ptr nonnull dereferenceable(5) @s4, i64 [[N]]) ; ANY-NEXT: call void @sink(ptr [[DST]], ptr [[ES4_N]]) @@ -448,6 +448,9 @@ define void @call_stpncpy_s(ptr %dst, ptr %src, i64 %n) { ret void } ;. -; ANY: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) } -; ANY: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } +; BE: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) } +; BE: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } +;. +; LE: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) } +; LE: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } ;. diff --git a/llvm/test/Transforms/InstCombine/str-int-2.ll b/llvm/test/Transforms/InstCombine/str-int-2.ll index a34714365e21..ae67422d1207 100644 --- a/llvm/test/Transforms/InstCombine/str-int-2.ll +++ b/llvm/test/Transforms/InstCombine/str-int-2.ll @@ -44,7 +44,7 @@ define i64 @strtol_hex() #0 { define i64 @strtol_endptr_not_null(ptr nonnull %pend) { ; CHECK-LABEL: @strtol_endptr_not_null( -; CHECK-NEXT: store ptr getelementptr inbounds ([3 x i8], ptr @.str, i64 0, i64 2), ptr [[PEND:%.*]], align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @.str, i64 2), ptr [[PEND:%.*]], align 8 ; CHECK-NEXT: ret i64 12 ; %call = call i64 @strtol(ptr @.str, ptr %pend, i32 10) diff --git a/llvm/test/Transforms/InstCombine/str-int-3.ll b/llvm/test/Transforms/InstCombine/str-int-3.ll index f319a16d211f..100f1a95b135 100644 --- a/llvm/test/Transforms/InstCombine/str-int-3.ll +++ b/llvm/test/Transforms/InstCombine/str-int-3.ll @@ -66,9 +66,9 @@ define void @fold_atoi_member(ptr %pi) { define void @fold_atoi_offset_out_of_bounds(ptr %pi) { ; CHECK-LABEL: @fold_atoi_offset_out_of_bounds( -; CHECK-NEXT: [[IA_0_0_32:%.*]] = call i32 @atoi(ptr nocapture nonnull getelementptr inbounds ([2 x %struct.A], ptr @a, i64 1, i64 0, i32 0, i64 0)) +; CHECK-NEXT: [[IA_0_0_32:%.*]] = call i32 @atoi(ptr nocapture nonnull getelementptr inbounds (i8, ptr @a, i64 32)) ; CHECK-NEXT: store i32 [[IA_0_0_32]], ptr [[PI:%.*]], align 4 -; CHECK-NEXT: [[IA_0_0_33:%.*]] = call i32 @atoi(ptr nocapture getelementptr ([2 x %struct.A], ptr @a, i64 1, i64 0, i32 0, i64 1)) +; CHECK-NEXT: [[IA_0_0_33:%.*]] = call i32 @atoi(ptr nocapture getelementptr (i8, ptr @a, i64 33)) ; CHECK-NEXT: store i32 [[IA_0_0_33]], ptr [[PI]], align 4 ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/InstCombine/str-int-4.ll b/llvm/test/Transforms/InstCombine/str-int-4.ll index 6efc5fb4ed1f..9173e122f8dd 100644 --- a/llvm/test/Transforms/InstCombine/str-int-4.ll +++ b/llvm/test/Transforms/InstCombine/str-int-4.ll @@ -42,39 +42,39 @@ declare i64 @strtoll(ptr, ptr, i32) define void @fold_strtol(ptr %ps) { ; CHECK-LABEL: @fold_strtol( -; CHECK-NEXT: store ptr getelementptr inbounds ([11 x i8], ptr @ws_im123, i64 0, i64 10), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @ws_im123, i64 10), ptr @endptr, align 8 ; CHECK-NEXT: store i32 -123, ptr [[PS:%.*]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([11 x i8], ptr @ws_ip234, i64 0, i64 10), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @ws_ip234, i64 10), ptr @endptr, align 8 ; CHECK-NEXT: [[PS1:%.*]] = getelementptr i8, ptr [[PS]], i64 4 ; CHECK-NEXT: store i32 234, ptr [[PS1]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([3 x i8], ptr @i0, i64 0, i64 2), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @i0, i64 2), ptr @endptr, align 8 ; CHECK-NEXT: [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i64 8 ; CHECK-NEXT: store i32 0, ptr [[PS2]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([3 x i8], ptr @i9, i64 0, i64 2), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @i9, i64 2), ptr @endptr, align 8 ; CHECK-NEXT: [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i64 12 ; CHECK-NEXT: store i32 9, ptr [[PS3]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([3 x i8], ptr @ia, i64 0, i64 2), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @ia, i64 2), ptr @endptr, align 8 ; CHECK-NEXT: [[PS4:%.*]] = getelementptr i8, ptr [[PS]], i64 16 ; CHECK-NEXT: store i32 10, ptr [[PS4]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([7 x i8], ptr @i19azAZ, i64 0, i64 6), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @i19azAZ, i64 6), ptr @endptr, align 8 ; CHECK-NEXT: [[PS5:%.*]] = getelementptr i8, ptr [[PS]], i64 20 ; CHECK-NEXT: store i32 76095035, ptr [[PS5]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([13 x i8], ptr @i32min, i64 0, i64 12), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @i32min, i64 12), ptr @endptr, align 8 ; CHECK-NEXT: [[PS6:%.*]] = getelementptr i8, ptr [[PS]], i64 24 ; CHECK-NEXT: store i32 -2147483648, ptr [[PS6]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([15 x i8], ptr @mo32min, i64 0, i64 14), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @mo32min, i64 14), ptr @endptr, align 8 ; CHECK-NEXT: [[PS7:%.*]] = getelementptr i8, ptr [[PS]], i64 28 ; CHECK-NEXT: store i32 -2147483648, ptr [[PS7]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([13 x i8], ptr @mx32min, i64 0, i64 12), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @mx32min, i64 12), ptr @endptr, align 8 ; CHECK-NEXT: [[PS8:%.*]] = getelementptr i8, ptr [[PS]], i64 32 ; CHECK-NEXT: store i32 -2147483648, ptr [[PS8]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([13 x i8], ptr @mx32min, i64 0, i64 12), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @mx32min, i64 12), ptr @endptr, align 8 ; CHECK-NEXT: [[PS9:%.*]] = getelementptr i8, ptr [[PS]], i64 36 ; CHECK-NEXT: store i32 -2147483648, ptr [[PS9]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([12 x i8], ptr @i32max, i64 0, i64 11), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @i32max, i64 11), ptr @endptr, align 8 ; CHECK-NEXT: [[PS10:%.*]] = getelementptr i8, ptr [[PS]], i64 40 ; CHECK-NEXT: store i32 2147483647, ptr [[PS10]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([12 x i8], ptr @x32max, i64 0, i64 11), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @x32max, i64 11), ptr @endptr, align 8 ; CHECK-NEXT: [[PS11:%.*]] = getelementptr i8, ptr [[PS]], i64 44 ; CHECK-NEXT: store i32 2147483647, ptr [[PS11]], align 4 ; CHECK-NEXT: ret void @@ -181,7 +181,7 @@ define void @call_strtol(ptr %ps) { ; CHECK-NEXT: [[NWS:%.*]] = call i32 @strtol(ptr nonnull @ws, ptr nonnull @endptr, i32 10) ; CHECK-NEXT: [[PS11:%.*]] = getelementptr i8, ptr [[PS]], i64 44 ; CHECK-NEXT: store i32 [[NWS]], ptr [[PS11]], align 4 -; CHECK-NEXT: [[NWSP6:%.*]] = call i32 @strtol(ptr nonnull getelementptr inbounds ([7 x i8], ptr @ws, i64 0, i64 6), ptr nonnull @endptr, i32 10) +; CHECK-NEXT: [[NWSP6:%.*]] = call i32 @strtol(ptr nonnull getelementptr inbounds (i8, ptr @ws, i64 6), ptr nonnull @endptr, i32 10) ; CHECK-NEXT: [[PS12:%.*]] = getelementptr i8, ptr [[PS]], i64 48 ; CHECK-NEXT: store i32 [[NWSP6]], ptr [[PS12]], align 4 ; CHECK-NEXT: [[I0B1:%.*]] = call i32 @strtol(ptr nonnull @i0, ptr nonnull @endptr, i32 1) @@ -287,15 +287,15 @@ define void @call_strtol(ptr %ps) { define void @fold_strtoll(ptr %ps) { ; CHECK-LABEL: @fold_strtoll( -; CHECK-NEXT: store ptr getelementptr inbounds ([11 x i8], ptr @ws_im123, i64 0, i64 10), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @ws_im123, i64 10), ptr @endptr, align 8 ; CHECK-NEXT: store i64 -123, ptr [[PS:%.*]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([11 x i8], ptr @ws_ip234, i64 0, i64 10), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @ws_ip234, i64 10), ptr @endptr, align 8 ; CHECK-NEXT: [[PS1:%.*]] = getelementptr i8, ptr [[PS]], i64 8 ; CHECK-NEXT: store i64 234, ptr [[PS1]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([22 x i8], ptr @i64min, i64 0, i64 21), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @i64min, i64 21), ptr @endptr, align 8 ; CHECK-NEXT: [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i64 16 ; CHECK-NEXT: store i64 -9223372036854775808, ptr [[PS2]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([21 x i8], ptr @i64max, i64 0, i64 20), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @i64max, i64 20), ptr @endptr, align 8 ; CHECK-NEXT: [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i64 24 ; CHECK-NEXT: store i64 9223372036854775807, ptr [[PS3]], align 4 ; CHECK-NEXT: ret void @@ -335,7 +335,7 @@ define void @call_strtoll(ptr %ps) { ; CHECK-NEXT: [[NWS:%.*]] = call i64 @strtoll(ptr nonnull @ws, ptr nonnull @endptr, i32 10) ; CHECK-NEXT: [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i64 16 ; CHECK-NEXT: store i64 [[NWS]], ptr [[PS2]], align 4 -; CHECK-NEXT: [[NWSP6:%.*]] = call i64 @strtoll(ptr nonnull getelementptr inbounds ([7 x i8], ptr @ws, i64 0, i64 6), ptr nonnull @endptr, i32 10) +; CHECK-NEXT: [[NWSP6:%.*]] = call i64 @strtoll(ptr nonnull getelementptr inbounds (i8, ptr @ws, i64 6), ptr nonnull @endptr, i32 10) ; CHECK-NEXT: [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i64 24 ; CHECK-NEXT: store i64 [[NWSP6]], ptr [[PS3]], align 4 ; CHECK-NEXT: ret void @@ -375,10 +375,10 @@ define void @call_strtol_trailing_space(ptr %ps) { ; CHECK-NEXT: [[N1:%.*]] = call i32 @strtol(ptr nonnull @i_1_2_3_, ptr nonnull @endptr, i32 10) ; CHECK-NEXT: [[PS1:%.*]] = getelementptr i8, ptr [[PS:%.*]], i64 4 ; CHECK-NEXT: store i32 [[N1]], ptr [[PS1]], align 4 -; CHECK-NEXT: [[N2:%.*]] = call i32 @strtol(ptr nonnull getelementptr inbounds ([9 x i8], ptr @i_1_2_3_, i64 0, i64 2), ptr nonnull @endptr, i32 10) +; CHECK-NEXT: [[N2:%.*]] = call i32 @strtol(ptr nonnull getelementptr inbounds (i8, ptr @i_1_2_3_, i64 2), ptr nonnull @endptr, i32 10) ; CHECK-NEXT: [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i64 8 ; CHECK-NEXT: store i32 [[N2]], ptr [[PS2]], align 4 -; CHECK-NEXT: [[N3:%.*]] = call i32 @strtol(ptr nonnull getelementptr inbounds ([9 x i8], ptr @i_1_2_3_, i64 0, i64 4), ptr nonnull @endptr, i32 10) +; CHECK-NEXT: [[N3:%.*]] = call i32 @strtol(ptr nonnull getelementptr inbounds (i8, ptr @i_1_2_3_, i64 4), ptr nonnull @endptr, i32 10) ; CHECK-NEXT: [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i64 12 ; CHECK-NEXT: store i32 [[N3]], ptr [[PS3]], align 4 ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/InstCombine/str-int-5.ll b/llvm/test/Transforms/InstCombine/str-int-5.ll index ff4f2bffd977..4ccf7ea6407c 100644 --- a/llvm/test/Transforms/InstCombine/str-int-5.ll +++ b/llvm/test/Transforms/InstCombine/str-int-5.ll @@ -46,39 +46,39 @@ declare i64 @strtoull(ptr, ptr, i32) define void @fold_strtoul(ptr %ps) { ; CHECK-LABEL: @fold_strtoul( -; CHECK-NEXT: store ptr getelementptr inbounds ([11 x i8], ptr @ws_im123, i64 0, i64 10), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @ws_im123, i64 10), ptr @endptr, align 8 ; CHECK-NEXT: store i32 -123, ptr [[PS:%.*]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([11 x i8], ptr @ws_ip234, i64 0, i64 10), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @ws_ip234, i64 10), ptr @endptr, align 8 ; CHECK-NEXT: [[PS1:%.*]] = getelementptr i8, ptr [[PS]], i64 4 ; CHECK-NEXT: store i32 234, ptr [[PS1]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([13 x i8], ptr @i32min_m1, i64 0, i64 12), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @i32min_m1, i64 12), ptr @endptr, align 8 ; CHECK-NEXT: [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i64 8 ; CHECK-NEXT: store i32 2147483647, ptr [[PS2]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([13 x i8], ptr @i32min, i64 0, i64 12), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @i32min, i64 12), ptr @endptr, align 8 ; CHECK-NEXT: [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i64 12 ; CHECK-NEXT: store i32 -2147483648, ptr [[PS3]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([15 x i8], ptr @o32min, i64 0, i64 14), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @o32min, i64 14), ptr @endptr, align 8 ; CHECK-NEXT: [[PS4:%.*]] = getelementptr i8, ptr [[PS]], i64 16 ; CHECK-NEXT: store i32 -2147483648, ptr [[PS4]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([15 x i8], ptr @mo32min, i64 0, i64 14), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @mo32min, i64 14), ptr @endptr, align 8 ; CHECK-NEXT: [[PS5:%.*]] = getelementptr i8, ptr [[PS]], i64 20 ; CHECK-NEXT: store i32 -2147483648, ptr [[PS5]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([13 x i8], ptr @x32min, i64 0, i64 12), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @x32min, i64 12), ptr @endptr, align 8 ; CHECK-NEXT: [[PS6:%.*]] = getelementptr i8, ptr [[PS]], i64 24 ; CHECK-NEXT: store i32 -2147483648, ptr [[PS6]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([13 x i8], ptr @mx32min, i64 0, i64 12), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @mx32min, i64 12), ptr @endptr, align 8 ; CHECK-NEXT: [[PS7:%.*]] = getelementptr i8, ptr [[PS]], i64 28 ; CHECK-NEXT: store i32 -2147483648, ptr [[PS7]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([12 x i8], ptr @i32max, i64 0, i64 11), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @i32max, i64 11), ptr @endptr, align 8 ; CHECK-NEXT: [[PS8:%.*]] = getelementptr i8, ptr [[PS]], i64 32 ; CHECK-NEXT: store i32 2147483647, ptr [[PS8]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([6 x i8], ptr @mX01, i64 0, i64 5), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @mX01, i64 5), ptr @endptr, align 8 ; CHECK-NEXT: [[PS9:%.*]] = getelementptr i8, ptr [[PS]], i64 36 ; CHECK-NEXT: store i32 -1, ptr [[PS9]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([12 x i8], ptr @i32max_p1, i64 0, i64 11), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @i32max_p1, i64 11), ptr @endptr, align 8 ; CHECK-NEXT: [[PS10:%.*]] = getelementptr i8, ptr [[PS]], i64 40 ; CHECK-NEXT: store i32 -2147483648, ptr [[PS10]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([12 x i8], ptr @ui32max, i64 0, i64 11), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @ui32max, i64 11), ptr @endptr, align 8 ; CHECK-NEXT: [[PS11:%.*]] = getelementptr i8, ptr [[PS]], i64 44 ; CHECK-NEXT: store i32 -1, ptr [[PS11]], align 4 ; CHECK-NEXT: ret void @@ -159,7 +159,7 @@ define void @call_strtoul(ptr %ps) { ; CHECK-NEXT: [[NWS:%.*]] = call i32 @strtoul(ptr nonnull @ws, ptr nonnull @endptr, i32 10) ; CHECK-NEXT: [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i64 8 ; CHECK-NEXT: store i32 [[NWS]], ptr [[PS2]], align 4 -; CHECK-NEXT: [[NWSP6:%.*]] = call i32 @strtoul(ptr nonnull getelementptr inbounds ([7 x i8], ptr @ws, i64 0, i64 6), ptr nonnull @endptr, i32 10) +; CHECK-NEXT: [[NWSP6:%.*]] = call i32 @strtoul(ptr nonnull getelementptr inbounds (i8, ptr @ws, i64 6), ptr nonnull @endptr, i32 10) ; CHECK-NEXT: [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i64 12 ; CHECK-NEXT: store i32 [[NWSP6]], ptr [[PS3]], align 4 ; CHECK-NEXT: ret void @@ -195,36 +195,36 @@ define void @call_strtoul(ptr %ps) { define void @fold_strtoull(ptr %ps) { ; CHECK-LABEL: @fold_strtoull( -; CHECK-NEXT: store ptr getelementptr inbounds ([11 x i8], ptr @ws_im123, i64 0, i64 10), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @ws_im123, i64 10), ptr @endptr, align 8 ; CHECK-NEXT: store i64 -123, ptr [[PS:%.*]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([11 x i8], ptr @ws_ip234, i64 0, i64 10), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @ws_ip234, i64 10), ptr @endptr, align 8 ; CHECK-NEXT: [[PS1:%.*]] = getelementptr i8, ptr [[PS]], i64 8 ; CHECK-NEXT: store i64 234, ptr [[PS1]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([22 x i8], ptr @i64min_m1, i64 0, i64 21), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @i64min_m1, i64 21), ptr @endptr, align 8 ; CHECK-NEXT: [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i64 16 ; CHECK-NEXT: store i64 9223372036854775807, ptr [[PS2]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([13 x i8], ptr @i32min, i64 0, i64 12), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @i32min, i64 12), ptr @endptr, align 8 ; CHECK-NEXT: [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i64 24 ; CHECK-NEXT: store i64 -2147483648, ptr [[PS3]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([15 x i8], ptr @o32min, i64 0, i64 14), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @o32min, i64 14), ptr @endptr, align 8 ; CHECK-NEXT: [[PS4:%.*]] = getelementptr i8, ptr [[PS]], i64 32 ; CHECK-NEXT: store i64 2147483648, ptr [[PS4]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([13 x i8], ptr @x32min, i64 0, i64 12), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @x32min, i64 12), ptr @endptr, align 8 ; CHECK-NEXT: [[PS5:%.*]] = getelementptr i8, ptr [[PS]], i64 40 ; CHECK-NEXT: store i64 2147483648, ptr [[PS5]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([22 x i8], ptr @i64min, i64 0, i64 21), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @i64min, i64 21), ptr @endptr, align 8 ; CHECK-NEXT: [[PS6:%.*]] = getelementptr i8, ptr [[PS]], i64 48 ; CHECK-NEXT: store i64 -9223372036854775808, ptr [[PS6]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([21 x i8], ptr @i64max, i64 0, i64 20), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @i64max, i64 20), ptr @endptr, align 8 ; CHECK-NEXT: [[PS7:%.*]] = getelementptr i8, ptr [[PS]], i64 56 ; CHECK-NEXT: store i64 9223372036854775807, ptr [[PS7]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([21 x i8], ptr @i64max_p1, i64 0, i64 20), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @i64max_p1, i64 20), ptr @endptr, align 8 ; CHECK-NEXT: [[PS8:%.*]] = getelementptr i8, ptr [[PS]], i64 64 ; CHECK-NEXT: store i64 -9223372036854775808, ptr [[PS8]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([22 x i8], ptr @ui64max, i64 0, i64 21), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @ui64max, i64 21), ptr @endptr, align 8 ; CHECK-NEXT: [[PS9:%.*]] = getelementptr i8, ptr [[PS]], i64 72 ; CHECK-NEXT: store i64 -1, ptr [[PS9]], align 4 -; CHECK-NEXT: store ptr getelementptr inbounds ([20 x i8], ptr @x64max, i64 0, i64 19), ptr @endptr, align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @x64max, i64 19), ptr @endptr, align 8 ; CHECK-NEXT: [[PS10:%.*]] = getelementptr i8, ptr [[PS]], i64 80 ; CHECK-NEXT: store i64 -1, ptr [[PS10]], align 4 ; CHECK-NEXT: ret void @@ -298,7 +298,7 @@ define void @call_strtoull(ptr %ps) { ; CHECK-NEXT: [[NWS:%.*]] = call i64 @strtoull(ptr nonnull @ws, ptr nonnull @endptr, i32 10) ; CHECK-NEXT: [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i64 16 ; CHECK-NEXT: store i64 [[NWS]], ptr [[PS2]], align 4 -; CHECK-NEXT: [[NWSP6:%.*]] = call i64 @strtoull(ptr nonnull getelementptr inbounds ([7 x i8], ptr @ws, i64 0, i64 6), ptr nonnull @endptr, i32 10) +; CHECK-NEXT: [[NWSP6:%.*]] = call i64 @strtoull(ptr nonnull getelementptr inbounds (i8, ptr @ws, i64 6), ptr nonnull @endptr, i32 10) ; CHECK-NEXT: [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i64 24 ; CHECK-NEXT: store i64 [[NWSP6]], ptr [[PS3]], align 4 ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/InstCombine/str-int.ll b/llvm/test/Transforms/InstCombine/str-int.ll index 718bfe413333..ee8d04d2f0e2 100644 --- a/llvm/test/Transforms/InstCombine/str-int.ll +++ b/llvm/test/Transforms/InstCombine/str-int.ll @@ -46,7 +46,7 @@ define i32 @strtol_hex() #0 { define i32 @strtol_endptr_not_null(ptr %pend) { ; CHECK-LABEL: @strtol_endptr_not_null( ; CHECK-NEXT: [[ENDP1:%.*]] = getelementptr inbounds i8, ptr [[PEND:%.*]], i64 8 -; CHECK-NEXT: store ptr getelementptr inbounds ([3 x i8], ptr @.str, i64 0, i64 2), ptr [[ENDP1]], align 8 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @.str, i64 2), ptr [[ENDP1]], align 8 ; CHECK-NEXT: ret i32 12 ; %endp1 = getelementptr inbounds ptr, ptr %pend, i32 1 diff --git a/llvm/test/Transforms/InstCombine/strcall-bad-sig.ll b/llvm/test/Transforms/InstCombine/strcall-bad-sig.ll index 5e59db5ef88a..7d3633a5d227 100644 --- a/llvm/test/Transforms/InstCombine/strcall-bad-sig.ll +++ b/llvm/test/Transforms/InstCombine/strcall-bad-sig.ll @@ -42,7 +42,7 @@ declare ptr @strncasecmp(ptr, ptr) define ptr @call_bad_strncasecmp() { ; CHECK-LABEL: @call_bad_strncasecmp( -; CHECK-NEXT: [[CMP:%.*]] = call ptr @strncasecmp(ptr nonnull @a, ptr nonnull getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1)) +; CHECK-NEXT: [[CMP:%.*]] = call ptr @strncasecmp(ptr nonnull @a, ptr nonnull getelementptr inbounds (i8, ptr @a, i64 1)) ; CHECK-NEXT: ret ptr [[CMP]] ; %p1 = getelementptr [2 x i8], ptr @a, i32 0, i32 1 @@ -55,7 +55,7 @@ declare i1 @strcoll(ptr, ptr, ptr) define i1 @call_bad_strcoll() { ; CHECK-LABEL: @call_bad_strcoll( -; CHECK-NEXT: [[I:%.*]] = call i1 @strcoll(ptr nonnull @a, ptr nonnull getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1), ptr nonnull @a) +; CHECK-NEXT: [[I:%.*]] = call i1 @strcoll(ptr nonnull @a, ptr nonnull getelementptr inbounds (i8, ptr @a, i64 1), ptr nonnull @a) ; CHECK-NEXT: ret i1 [[I]] ; %p1 = getelementptr [2 x i8], ptr @a, i32 0, i32 1 @@ -80,7 +80,7 @@ declare i1 @strtok(ptr, ptr, i1) define i1 @call_bad_strtok() { ; CHECK-LABEL: @call_bad_strtok( -; CHECK-NEXT: [[RET:%.*]] = call i1 @strtok(ptr nonnull @a, ptr nonnull getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1), i1 false) +; CHECK-NEXT: [[RET:%.*]] = call i1 @strtok(ptr nonnull @a, ptr nonnull getelementptr inbounds (i8, ptr @a, i64 1), i1 false) ; CHECK-NEXT: ret i1 [[RET]] ; %p1 = getelementptr [2 x i8], ptr @a, i32 0, i32 1 @@ -94,7 +94,7 @@ declare i1 @strtok_r(ptr, ptr) define i1 @call_bad_strtok_r() { ; CHECK-LABEL: @call_bad_strtok_r( -; CHECK-NEXT: [[RET:%.*]] = call i1 @strtok_r(ptr nonnull @a, ptr nonnull getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1)) +; CHECK-NEXT: [[RET:%.*]] = call i1 @strtok_r(ptr nonnull @a, ptr nonnull getelementptr inbounds (i8, ptr @a, i64 1)) ; CHECK-NEXT: ret i1 [[RET]] ; %p1 = getelementptr [2 x i8], ptr @a, i32 0, i32 1 @@ -146,7 +146,7 @@ declare ptr @strxfrm(ptr, ptr) define ptr @call_bad_strxfrm() { ; CHECK-LABEL: @call_bad_strxfrm( -; CHECK-NEXT: [[RET:%.*]] = call ptr @strxfrm(ptr nonnull @a, ptr nonnull getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1)) +; CHECK-NEXT: [[RET:%.*]] = call ptr @strxfrm(ptr nonnull @a, ptr nonnull getelementptr inbounds (i8, ptr @a, i64 1)) ; CHECK-NEXT: ret ptr [[RET]] ; %p1 = getelementptr [2 x i8], ptr @a, i32 0, i32 1 diff --git a/llvm/test/Transforms/InstCombine/strcall-no-nul.ll b/llvm/test/Transforms/InstCombine/strcall-no-nul.ll index 30221ad5b096..96905a273319 100644 --- a/llvm/test/Transforms/InstCombine/strcall-no-nul.ll +++ b/llvm/test/Transforms/InstCombine/strcall-no-nul.ll @@ -50,7 +50,7 @@ declare i32 @snprintf(ptr, i64, ptr, ...) define ptr @fold_strchr_past_end() { ; CHECK-LABEL: @fold_strchr_past_end( -; CHECK-NEXT: ret ptr getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @a5, i64 5) ; %p = getelementptr [5 x i8], ptr @a5, i32 0, i32 5 %q = call ptr @strchr(ptr %p, i32 0) @@ -268,7 +268,7 @@ define void @fold_strcspn_past_end(ptr %poff) { define i32 @fold_atoi_past_end() { ; CHECK-LABEL: @fold_atoi_past_end( -; CHECK-NEXT: [[I:%.*]] = call i32 @atoi(ptr nocapture nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0)) +; CHECK-NEXT: [[I:%.*]] = call i32 @atoi(ptr nocapture nonnull getelementptr inbounds (i8, ptr @a5, i64 5)) ; CHECK-NEXT: ret i32 [[I]] ; %p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 5 @@ -282,21 +282,21 @@ define i32 @fold_atoi_past_end() { define void @fold_atol_strtol_past_end(ptr %ps) { ; CHECK-LABEL: @fold_atol_strtol_past_end( -; CHECK-NEXT: [[I0:%.*]] = call i64 @atol(ptr nocapture nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0)) +; CHECK-NEXT: [[I0:%.*]] = call i64 @atol(ptr nocapture nonnull getelementptr inbounds (i8, ptr @a5, i64 5)) ; CHECK-NEXT: store i64 [[I0]], ptr [[PS:%.*]], align 4 -; CHECK-NEXT: [[I1:%.*]] = call i64 @atoll(ptr nocapture nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0)) +; CHECK-NEXT: [[I1:%.*]] = call i64 @atoll(ptr nocapture nonnull getelementptr inbounds (i8, ptr @a5, i64 5)) ; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[PS]], i64 8 ; CHECK-NEXT: store i64 [[I1]], ptr [[P1]], align 4 -; CHECK-NEXT: [[I2:%.*]] = call i64 @strtol(ptr nocapture nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0), ptr null, i32 0) +; CHECK-NEXT: [[I2:%.*]] = call i64 @strtol(ptr nocapture nonnull getelementptr inbounds (i8, ptr @a5, i64 5), ptr null, i32 0) ; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[PS]], i64 16 ; CHECK-NEXT: store i64 [[I2]], ptr [[P2]], align 4 -; CHECK-NEXT: [[I3:%.*]] = call i64 @strtoul(ptr nocapture nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0), ptr null, i32 8) +; CHECK-NEXT: [[I3:%.*]] = call i64 @strtoul(ptr nocapture nonnull getelementptr inbounds (i8, ptr @a5, i64 5), ptr null, i32 8) ; CHECK-NEXT: [[P3:%.*]] = getelementptr i8, ptr [[PS]], i64 24 ; CHECK-NEXT: store i64 [[I3]], ptr [[P3]], align 4 -; CHECK-NEXT: [[I4:%.*]] = call i64 @strtoll(ptr nocapture nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0), ptr null, i32 10) +; CHECK-NEXT: [[I4:%.*]] = call i64 @strtoll(ptr nocapture nonnull getelementptr inbounds (i8, ptr @a5, i64 5), ptr null, i32 10) ; CHECK-NEXT: [[P4:%.*]] = getelementptr i8, ptr [[PS]], i64 32 ; CHECK-NEXT: store i64 [[I4]], ptr [[P4]], align 4 -; CHECK-NEXT: [[I5:%.*]] = call i64 @strtoul(ptr nocapture nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0), ptr null, i32 16) +; CHECK-NEXT: [[I5:%.*]] = call i64 @strtoul(ptr nocapture nonnull getelementptr inbounds (i8, ptr @a5, i64 5), ptr null, i32 16) ; CHECK-NEXT: [[P5:%.*]] = getelementptr i8, ptr [[PS]], i64 40 ; CHECK-NEXT: store i64 [[I5]], ptr [[P5]], align 4 ; CHECK-NEXT: ret void @@ -358,9 +358,9 @@ define void @fold_sprintf_past_end(ptr %pcnt, ptr %dst) { define void @fold_snprintf_past_end(ptr %pcnt, ptr %dst, i64 %n) { ; CHECK-LABEL: @fold_snprintf_past_end( -; CHECK-NEXT: [[N5_:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[DST:%.*]], i64 [[N:%.*]], ptr nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0)) +; CHECK-NEXT: [[N5_:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[DST:%.*]], i64 [[N:%.*]], ptr nonnull getelementptr inbounds (i8, ptr @a5, i64 5)) ; CHECK-NEXT: store i32 [[N5_]], ptr [[PCNT:%.*]], align 4 -; CHECK-NEXT: [[N05:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[DST]], i64 [[N]], ptr nonnull @a5, ptr nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0)) +; CHECK-NEXT: [[N05:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[DST]], i64 [[N]], ptr nonnull @a5, ptr nonnull getelementptr inbounds (i8, ptr @a5, i64 5)) ; CHECK-NEXT: [[PN05:%.*]] = getelementptr i8, ptr [[PCNT]], i64 4 ; CHECK-NEXT: store i32 [[N05]], ptr [[PN05]], align 4 ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/InstCombine/strchr-1.ll b/llvm/test/Transforms/InstCombine/strchr-1.ll index 191e0a18fced..0cedc3ad5181 100644 --- a/llvm/test/Transforms/InstCombine/strchr-1.ll +++ b/llvm/test/Transforms/InstCombine/strchr-1.ll @@ -13,7 +13,7 @@ declare ptr @strchr(ptr, i32) define void @test_simplify1() { ; CHECK-LABEL: @test_simplify1( -; CHECK-NEXT: store ptr getelementptr inbounds ([14 x i8], ptr @hello, i32 0, i32 6), ptr @chp, align 4 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @hello, i32 6), ptr @chp, align 4 ; CHECK-NEXT: ret void ; @@ -35,7 +35,7 @@ define void @test_simplify2() { define void @test_simplify3() { ; CHECK-LABEL: @test_simplify3( -; CHECK-NEXT: store ptr getelementptr inbounds ([14 x i8], ptr @hello, i32 0, i32 13), ptr @chp, align 4 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @hello, i32 13), ptr @chp, align 4 ; CHECK-NEXT: ret void ; @@ -58,7 +58,7 @@ define void @test_simplify4(i32 %chr) { define void @test_simplify5() { ; CHECK-LABEL: @test_simplify5( -; CHECK-NEXT: store ptr getelementptr inbounds ([14 x i8], ptr @hello, i32 0, i32 13), ptr @chp, align 4 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @hello, i32 13), ptr @chp, align 4 ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/InstCombine/strchr-3.ll b/llvm/test/Transforms/InstCombine/strchr-3.ll index 55fb44563920..7cbbdf8c69bc 100644 --- a/llvm/test/Transforms/InstCombine/strchr-3.ll +++ b/llvm/test/Transforms/InstCombine/strchr-3.ll @@ -20,7 +20,7 @@ define ptr @fold_strchr_s1_C(i32 %C) { ; CHECK-LABEL: @fold_strchr_s1_C( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0 -; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds ([2 x i8], ptr @s1, i64 0, i64 1), ptr null +; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds (i8, ptr @s1, i64 1), ptr null ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8 [[TMP1]], 1 ; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP3]], ptr @s1, ptr [[MEMCHR_SEL1]] ; CHECK-NEXT: ret ptr [[MEMCHR_SEL2]] @@ -36,7 +36,7 @@ define ptr @fold_strchr_s11_C(i32 %C) { ; CHECK-LABEL: @fold_strchr_s11_C( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0 -; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds ([3 x i8], ptr @s11, i64 0, i64 2), ptr null +; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds (i8, ptr @s11, i64 2), ptr null ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8 [[TMP1]], 1 ; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP3]], ptr @s11, ptr [[MEMCHR_SEL1]] ; CHECK-NEXT: ret ptr [[MEMCHR_SEL2]] @@ -52,7 +52,7 @@ define ptr @fold_strchr_s111_C(i32 %C) { ; CHECK-LABEL: @fold_strchr_s111_C( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0 -; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds ([4 x i8], ptr @s111, i64 0, i64 3), ptr null +; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds (i8, ptr @s111, i64 3), ptr null ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8 [[TMP1]], 1 ; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP3]], ptr @s111, ptr [[MEMCHR_SEL1]] ; CHECK-NEXT: ret ptr [[MEMCHR_SEL2]] @@ -96,9 +96,9 @@ define ptr @fold_strchr_s21111p1_C(i32 %C) { ; CHECK-LABEL: @fold_strchr_s21111p1_C( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0 -; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds ([6 x i8], ptr @s21111, i64 0, i64 5), ptr null +; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds (i8, ptr @s21111, i64 5), ptr null ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8 [[TMP1]], 1 -; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP3]], ptr getelementptr inbounds ([6 x i8], ptr @s21111, i64 0, i64 1), ptr [[MEMCHR_SEL1]] +; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP3]], ptr getelementptr inbounds (i8, ptr @s21111, i64 1), ptr [[MEMCHR_SEL1]] ; CHECK-NEXT: ret ptr [[MEMCHR_SEL2]] ; %ptr = getelementptr inbounds [6 x i8], ptr @s21111, i64 0, i64 1 @@ -113,7 +113,7 @@ define ptr @fold_strchr_s11102_C(i32 %C) { ; CHECK-LABEL: @fold_strchr_s11102_C( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0 -; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds ([6 x i8], ptr @s11102, i64 0, i64 3), ptr null +; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds (i8, ptr @s11102, i64 3), ptr null ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8 [[TMP1]], 1 ; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP3]], ptr @s11102, ptr [[MEMCHR_SEL1]] ; CHECK-NEXT: ret ptr [[MEMCHR_SEL2]] diff --git a/llvm/test/Transforms/InstCombine/strcmp-4.ll b/llvm/test/Transforms/InstCombine/strcmp-4.ll index bdd521ddb909..e96c28b780b2 100644 --- a/llvm/test/Transforms/InstCombine/strcmp-4.ll +++ b/llvm/test/Transforms/InstCombine/strcmp-4.ll @@ -11,8 +11,8 @@ declare i32 @strcmp(ptr, ptr) define i32 @fold_strcmp_s3_x_s4_s3(i1 %C) { ; CHECK-LABEL: @fold_strcmp_s3_x_s4_s3( -; CHECK-NEXT: [[PTR:%.*]] = select i1 [[C:%.*]], ptr getelementptr inbounds ([10 x i8], ptr @s9, i64 0, i64 6), ptr getelementptr inbounds ([10 x i8], ptr @s9, i64 0, i64 5) -; CHECK-NEXT: [[CMP:%.*]] = call i32 @strcmp(ptr noundef nonnull dereferenceable(1) [[PTR]], ptr noundef nonnull dereferenceable(4) getelementptr inbounds ([10 x i8], ptr @s9, i64 0, i64 6)) +; CHECK-NEXT: [[PTR:%.*]] = select i1 [[C:%.*]], ptr getelementptr inbounds (i8, ptr @s9, i64 6), ptr getelementptr inbounds (i8, ptr @s9, i64 5) +; CHECK-NEXT: [[CMP:%.*]] = call i32 @strcmp(ptr noundef nonnull dereferenceable(1) [[PTR]], ptr noundef nonnull dereferenceable(4) getelementptr inbounds (i8, ptr @s9, i64 6)) ; CHECK-NEXT: ret i32 [[CMP]] ; diff --git a/llvm/test/Transforms/InstCombine/strlcpy-1.ll b/llvm/test/Transforms/InstCombine/strlcpy-1.ll index bfa4fc11d310..7ca6c1599f19 100644 --- a/llvm/test/Transforms/InstCombine/strlcpy-1.ll +++ b/llvm/test/Transforms/InstCombine/strlcpy-1.ll @@ -235,9 +235,9 @@ define void @call_strlcpy_s0_n(ptr %dst, ptr %s, i64 %n) { ; ANY-NEXT: [[NZ:%.*]] = or i64 [[N]], 1 ; ANY-NEXT: [[NS_NZ:%.*]] = call i64 @strlcpy(ptr noundef nonnull dereferenceable(1) [[DST]], ptr noundef nonnull dereferenceable(1) [[S]], i64 [[NZ]]) ; ANY-NEXT: call void @sink(ptr [[DST]], i64 [[NS_NZ]]) -; ANY-NEXT: [[NS0_N:%.*]] = call i64 @strlcpy(ptr [[DST]], ptr noundef nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], ptr @s4, i64 0, i64 4), i64 [[N]]) +; ANY-NEXT: [[NS0_N:%.*]] = call i64 @strlcpy(ptr [[DST]], ptr noundef nonnull dereferenceable(1) getelementptr inbounds (i8, ptr @s4, i64 4), i64 [[N]]) ; ANY-NEXT: call void @sink(ptr [[DST]], i64 [[NS0_N]]) -; ANY-NEXT: [[NS1_N:%.*]] = call i64 @strlcpy(ptr [[DST]], ptr noundef nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], ptr @s4, i64 0, i64 3), i64 [[N]]) +; ANY-NEXT: [[NS1_N:%.*]] = call i64 @strlcpy(ptr [[DST]], ptr noundef nonnull dereferenceable(1) getelementptr inbounds (i8, ptr @s4, i64 3), i64 [[N]]) ; ANY-NEXT: call void @sink(ptr [[DST]], i64 [[NS1_N]]) ; ANY-NEXT: [[NS4_N:%.*]] = call i64 @strlcpy(ptr [[DST]], ptr noundef nonnull dereferenceable(1) @s4, i64 [[N]]) ; ANY-NEXT: call void @sink(ptr [[DST]], i64 [[NS4_N]]) diff --git a/llvm/test/Transforms/InstCombine/strlen-1.ll b/llvm/test/Transforms/InstCombine/strlen-1.ll index bd4c4a2ce47e..8def4dd9747f 100644 --- a/llvm/test/Transforms/InstCombine/strlen-1.ll +++ b/llvm/test/Transforms/InstCombine/strlen-1.ll @@ -235,7 +235,7 @@ define i1 @strlen0_after_write_to_first_byte_global() { define i1 @strlen0_after_write_to_second_byte_global() { ; CHECK-LABEL: @strlen0_after_write_to_second_byte_global( -; CHECK-NEXT: store i8 49, ptr getelementptr inbounds ([32 x i8], ptr @a, i32 0, i32 1), align 16 +; CHECK-NEXT: store i8 49, ptr getelementptr inbounds (i8, ptr @a, i32 1), align 16 ; CHECK-NEXT: [[CHAR0:%.*]] = load i8, ptr @a, align 1 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[CHAR0]], 0 ; CHECK-NEXT: ret i1 [[CMP]] diff --git a/llvm/test/Transforms/InstCombine/strlen-6.ll b/llvm/test/Transforms/InstCombine/strlen-6.ll index f1fe715d3893..25e653362db8 100644 --- a/llvm/test/Transforms/InstCombine/strlen-6.ll +++ b/llvm/test/Transforms/InstCombine/strlen-6.ll @@ -103,7 +103,7 @@ define i64 @fold_strlen_a_S3_p2_s4_to_1() { define void @fold_strlen_a_s3_S4_to_4() { ; CHECK-LABEL: @fold_strlen_a_s3_S4_to_4( ; CHECK-NEXT: store i64 4, ptr @ax, align 4 -; CHECK-NEXT: store i64 4, ptr getelementptr inbounds ([0 x i64], ptr @ax, i64 0, i64 1), align 4 +; CHECK-NEXT: store i64 4, ptr getelementptr inbounds (i8, ptr @ax, i64 8), align 4 ; CHECK-NEXT: ret void ; %p1 = getelementptr %struct.A_a4_a5, ptr @a_s3_s4, i32 0, i32 0, i32 4 @@ -125,7 +125,7 @@ define void @fold_strlen_a_s3_S4_to_4() { define void @fold_strlen_a_s3_S4_p1_to_3() { ; CHECK-LABEL: @fold_strlen_a_s3_S4_p1_to_3( ; CHECK-NEXT: store i64 3, ptr @ax, align 4 -; CHECK-NEXT: store i64 3, ptr getelementptr inbounds ([0 x i64], ptr @ax, i64 0, i64 1), align 4 +; CHECK-NEXT: store i64 3, ptr getelementptr inbounds (i8, ptr @ax, i64 8), align 4 ; CHECK-NEXT: ret void ; %p1 = getelementptr %struct.A_a4_a5, ptr @a_s3_s4, i32 0, i32 0, i32 5 @@ -147,7 +147,7 @@ define void @fold_strlen_a_s3_S4_p1_to_3() { define void @fold_strlen_a_s3_i32_S4_to_4() { ; CHECK-LABEL: @fold_strlen_a_s3_i32_S4_to_4( ; CHECK-NEXT: store i64 4, ptr @ax, align 4 -; CHECK-NEXT: store i64 4, ptr getelementptr inbounds ([0 x i64], ptr @ax, i64 0, i64 1), align 4 +; CHECK-NEXT: store i64 4, ptr getelementptr inbounds (i8, ptr @ax, i64 8), align 4 ; CHECK-NEXT: ret void ; %p1 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 0, i32 8 @@ -169,7 +169,7 @@ define void @fold_strlen_a_s3_i32_S4_to_4() { define void @fold_strlen_a_s3_i32_S4_p1_to_3() { ; CHECK-LABEL: @fold_strlen_a_s3_i32_S4_p1_to_3( ; CHECK-NEXT: store i64 3, ptr @ax, align 4 -; CHECK-NEXT: store i64 3, ptr getelementptr inbounds ([0 x i64], ptr @ax, i64 0, i64 1), align 4 +; CHECK-NEXT: store i64 3, ptr getelementptr inbounds (i8, ptr @ax, i64 8), align 4 ; CHECK-NEXT: ret void ; %p1 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 0, i32 9 @@ -191,7 +191,7 @@ define void @fold_strlen_a_s3_i32_S4_p1_to_3() { define void @fold_strlen_a_s3_i32_S4_p2_to_2() { ; CHECK-LABEL: @fold_strlen_a_s3_i32_S4_p2_to_2( ; CHECK-NEXT: store i64 2, ptr @ax, align 4 -; CHECK-NEXT: store i64 2, ptr getelementptr inbounds ([0 x i64], ptr @ax, i64 0, i64 1), align 4 +; CHECK-NEXT: store i64 2, ptr getelementptr inbounds (i8, ptr @ax, i64 8), align 4 ; CHECK-NEXT: ret void ; %p1 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 0, i32 10 @@ -213,7 +213,7 @@ define void @fold_strlen_a_s3_i32_S4_p2_to_2() { define void @fold_strlen_a_s3_i32_S4_p3_to_1() { ; CHECK-LABEL: @fold_strlen_a_s3_i32_S4_p3_to_1( ; CHECK-NEXT: store i64 1, ptr @ax, align 4 -; CHECK-NEXT: store i64 1, ptr getelementptr inbounds ([0 x i64], ptr @ax, i64 0, i64 1), align 4 +; CHECK-NEXT: store i64 1, ptr getelementptr inbounds (i8, ptr @ax, i64 8), align 4 ; CHECK-NEXT: ret void ; %p1 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 0, i32 11 @@ -235,7 +235,7 @@ define void @fold_strlen_a_s3_i32_S4_p3_to_1() { define void @fold_strlen_a_s3_i32_S4_p4_to_0() { ; CHECK-LABEL: @fold_strlen_a_s3_i32_S4_p4_to_0( ; CHECK-NEXT: store i64 0, ptr @ax, align 4 -; CHECK-NEXT: store i64 0, ptr getelementptr inbounds ([0 x i64], ptr @ax, i64 0, i64 1), align 4 +; CHECK-NEXT: store i64 0, ptr getelementptr inbounds (i8, ptr @ax, i64 8), align 4 ; CHECK-NEXT: ret void ; %p1 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 0, i32 12 @@ -257,8 +257,8 @@ define void @fold_strlen_a_s3_i32_S4_p4_to_0() { define void @fold_strlen_ax_s() { ; CHECK-LABEL: @fold_strlen_ax_s( ; CHECK-NEXT: store i64 3, ptr @ax, align 4 -; CHECK-NEXT: store i64 5, ptr getelementptr inbounds ([0 x i64], ptr @ax, i64 0, i64 1), align 4 -; CHECK-NEXT: store i64 7, ptr getelementptr inbounds ([0 x i64], ptr @ax, i64 0, i64 2), align 4 +; CHECK-NEXT: store i64 5, ptr getelementptr inbounds (i8, ptr @ax, i64 8), align 4 +; CHECK-NEXT: store i64 7, ptr getelementptr inbounds (i8, ptr @ax, i64 16), align 4 ; CHECK-NEXT: ret void ; %pax_s3 = getelementptr { i8, [4 x i8] }, ptr @ax_s3, i64 0, i32 1, i64 0 diff --git a/llvm/test/Transforms/InstCombine/strpbrk-1.ll b/llvm/test/Transforms/InstCombine/strpbrk-1.ll index 411bd8d627ec..b51071df25d2 100644 --- a/llvm/test/Transforms/InstCombine/strpbrk-1.ll +++ b/llvm/test/Transforms/InstCombine/strpbrk-1.ll @@ -37,7 +37,7 @@ define ptr @test_simplify2(ptr %pat) { define ptr @test_simplify3() { ; CHECK-LABEL: @test_simplify3( -; CHECK-NEXT: ret ptr getelementptr inbounds ([12 x i8], ptr @hello, i32 0, i32 6) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @hello, i32 6) ; %ret = call ptr @strpbrk(ptr @hello, ptr @w) diff --git a/llvm/test/Transforms/InstCombine/strrchr-1.ll b/llvm/test/Transforms/InstCombine/strrchr-1.ll index 661e040f8042..0c876b9d2a98 100644 --- a/llvm/test/Transforms/InstCombine/strrchr-1.ll +++ b/llvm/test/Transforms/InstCombine/strrchr-1.ll @@ -12,7 +12,7 @@ declare ptr @strrchr(ptr, i32) define void @test_simplify1() { ; CHECK-LABEL: @test_simplify1( -; CHECK-NEXT: store ptr getelementptr inbounds ([14 x i8], ptr @hello, i32 0, i32 6), ptr @chp, align 4 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @hello, i32 6), ptr @chp, align 4 ; CHECK-NEXT: ret void ; @@ -34,7 +34,7 @@ define void @test_simplify2() { define void @test_simplify3() { ; CHECK-LABEL: @test_simplify3( -; CHECK-NEXT: store ptr getelementptr inbounds ([14 x i8], ptr @hello, i32 0, i32 13), ptr @chp, align 4 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @hello, i32 13), ptr @chp, align 4 ; CHECK-NEXT: ret void ; @@ -45,7 +45,7 @@ define void @test_simplify3() { define void @test_simplify4() { ; CHECK-LABEL: @test_simplify4( -; CHECK-NEXT: store ptr getelementptr inbounds ([14 x i8], ptr @hello, i32 0, i32 13), ptr @chp, align 4 +; CHECK-NEXT: store ptr getelementptr inbounds (i8, ptr @hello, i32 13), ptr @chp, align 4 ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/InstCombine/strrchr-3.ll b/llvm/test/Transforms/InstCombine/strrchr-3.ll index 1dadb0487871..f25504a8db2b 100644 --- a/llvm/test/Transforms/InstCombine/strrchr-3.ll +++ b/llvm/test/Transforms/InstCombine/strrchr-3.ll @@ -13,7 +13,7 @@ define ptr @fold_strrchr_sp10_x(i32 %c) { ; CHECK-LABEL: @fold_strrchr_sp10_x( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8 ; CHECK-NEXT: [[MEMRCHR_CHAR0CMP:%.*]] = icmp eq i8 [[TMP1]], 0 -; CHECK-NEXT: [[MEMRCHR_SEL:%.*]] = select i1 [[MEMRCHR_CHAR0CMP]], ptr getelementptr inbounds ([11 x i8], ptr @s10, i64 0, i64 10), ptr null +; CHECK-NEXT: [[MEMRCHR_SEL:%.*]] = select i1 [[MEMRCHR_CHAR0CMP]], ptr getelementptr inbounds (i8, ptr @s10, i64 10), ptr null ; CHECK-NEXT: ret ptr [[MEMRCHR_SEL]] ; %psp10 = getelementptr [11 x i8], ptr @s10, i32 0, i32 10 @@ -26,7 +26,7 @@ define ptr @fold_strrchr_sp10_x(i32 %c) { define ptr @call_strrchr_sp9_x(i32 %c) { ; CHECK-LABEL: @call_strrchr_sp9_x( -; CHECK-NEXT: [[MEMRCHR:%.*]] = call ptr @memrchr(ptr noundef nonnull dereferenceable(2) getelementptr inbounds ([11 x i8], ptr @s10, i64 0, i64 9), i32 [[C:%.*]], i64 2) +; CHECK-NEXT: [[MEMRCHR:%.*]] = call ptr @memrchr(ptr noundef nonnull dereferenceable(2) getelementptr inbounds (i8, ptr @s10, i64 9), i32 [[C:%.*]], i64 2) ; CHECK-NEXT: ret ptr [[MEMRCHR]] ; %psp9 = getelementptr [11 x i8], ptr @s10, i32 0, i32 9 @@ -40,7 +40,7 @@ define ptr @call_strrchr_sp9_x(i32 %c) { define ptr @call_strrchr_sp2_x(i32 %c) { ; CHECK-LABEL: @call_strrchr_sp2_x( -; CHECK-NEXT: [[MEMRCHR:%.*]] = call ptr @memrchr(ptr noundef nonnull dereferenceable(9) getelementptr inbounds ([11 x i8], ptr @s10, i64 0, i64 2), i32 [[C:%.*]], i64 9) +; CHECK-NEXT: [[MEMRCHR:%.*]] = call ptr @memrchr(ptr noundef nonnull dereferenceable(9) getelementptr inbounds (i8, ptr @s10, i64 2), i32 [[C:%.*]], i64 9) ; CHECK-NEXT: ret ptr [[MEMRCHR]] ; %psp2 = getelementptr [11 x i8], ptr @s10, i32 0, i32 2 @@ -53,7 +53,7 @@ define ptr @call_strrchr_sp2_x(i32 %c) { define ptr @call_strrchr_sp1_x(i32 %c) { ; CHECK-LABEL: @call_strrchr_sp1_x( -; CHECK-NEXT: [[MEMRCHR:%.*]] = call ptr @memrchr(ptr noundef nonnull dereferenceable(10) getelementptr inbounds ([11 x i8], ptr @s10, i64 0, i64 1), i32 [[C:%.*]], i64 10) +; CHECK-NEXT: [[MEMRCHR:%.*]] = call ptr @memrchr(ptr noundef nonnull dereferenceable(10) getelementptr inbounds (i8, ptr @s10, i64 1), i32 [[C:%.*]], i64 10) ; CHECK-NEXT: ret ptr [[MEMRCHR]] ; %psp1 = getelementptr [11 x i8], ptr @s10, i32 0, i32 1 diff --git a/llvm/test/Transforms/InstCombine/strstr-1.ll b/llvm/test/Transforms/InstCombine/strstr-1.ll index 50edbfffb9f8..b5f4a2ce288d 100644 --- a/llvm/test/Transforms/InstCombine/strstr-1.ll +++ b/llvm/test/Transforms/InstCombine/strstr-1.ll @@ -37,7 +37,7 @@ define ptr @test_simplify2(ptr %str) { define ptr @test_simplify3() { ; CHECK-LABEL: @test_simplify3( -; CHECK-NEXT: ret ptr getelementptr inbounds ([6 x i8], ptr @.str2, i64 0, i64 1) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @.str2, i64 1) ; %ret = call ptr @strstr(ptr @.str2, ptr @.str3) ret ptr %ret diff --git a/llvm/test/Transforms/InstCombine/vec_demanded_elts-inseltpoison.ll b/llvm/test/Transforms/InstCombine/vec_demanded_elts-inseltpoison.ll index 738ef1bc1ad2..74465cde86ad 100644 --- a/llvm/test/Transforms/InstCombine/vec_demanded_elts-inseltpoison.ll +++ b/llvm/test/Transforms/InstCombine/vec_demanded_elts-inseltpoison.ll @@ -566,7 +566,7 @@ define ptr @gep_cvbase_w_s_idx(<2 x ptr> %base, i64 %raw_addr) { define ptr @gep_cvbase_w_cv_idx(<2 x ptr> %base, i64 %raw_addr) { ; CHECK-LABEL: @gep_cvbase_w_cv_idx( -; CHECK-NEXT: ret ptr getelementptr inbounds (i32, ptr @GLOBAL, i64 1) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @GLOBAL, i64 4) ; %gep = getelementptr i32, <2 x ptr> , <2 x i64> %ee = extractelement <2 x ptr> %gep, i32 1 diff --git a/llvm/test/Transforms/InstCombine/vec_demanded_elts.ll b/llvm/test/Transforms/InstCombine/vec_demanded_elts.ll index fd55a236e0d7..d8a3b87f78ee 100644 --- a/llvm/test/Transforms/InstCombine/vec_demanded_elts.ll +++ b/llvm/test/Transforms/InstCombine/vec_demanded_elts.ll @@ -569,7 +569,7 @@ define ptr @gep_cvbase_w_s_idx(<2 x ptr> %base, i64 %raw_addr) { define ptr @gep_cvbase_w_cv_idx(<2 x ptr> %base, i64 %raw_addr) { ; CHECK-LABEL: @gep_cvbase_w_cv_idx( -; CHECK-NEXT: ret ptr getelementptr inbounds (i32, ptr @GLOBAL, i64 1) +; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @GLOBAL, i64 4) ; %gep = getelementptr i32, <2 x ptr> , <2 x i64> %ee = extractelement <2 x ptr> %gep, i32 1 diff --git a/llvm/test/Transforms/InstCombine/wcslen-1.ll b/llvm/test/Transforms/InstCombine/wcslen-1.ll index 138b3ff585c5..8833754a5367 100644 --- a/llvm/test/Transforms/InstCombine/wcslen-1.ll +++ b/llvm/test/Transforms/InstCombine/wcslen-1.ll @@ -231,7 +231,7 @@ define i64 @fold_wcslen_1() { ; with an offset that isn't a multiple of the element size). define i64 @no_fold_wcslen_1() { ; CHECK-LABEL: @no_fold_wcslen_1( -; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(ptr getelementptr ([15 x i8], ptr @ws, i64 0, i64 3)) +; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull getelementptr inbounds (i8, ptr @ws, i64 3)) ; CHECK-NEXT: ret i64 [[LEN]] ; %p = getelementptr [15 x i8], ptr @ws, i64 0, i64 3 @@ -246,7 +246,7 @@ define i64 @no_fold_wcslen_1() { ; with an offset that isn't a multiple of the element size). define i64 @no_fold_wcslen_2() { ; CHECK-LABEL: @no_fold_wcslen_2( -; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull getelementptr inbounds ([10 x i8], ptr @s8, i64 0, i64 3)) +; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(ptr nonnull getelementptr inbounds (i8, ptr @s8, i64 3)) ; CHECK-NEXT: ret i64 [[LEN]] ; %p = getelementptr [10 x i8], ptr @s8, i64 0, i64 3 diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/gep-alias.ll b/llvm/test/Transforms/InstSimplify/ConstProp/gep-alias.ll index f77a49e90be7..097ccfe78e97 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/gep-alias.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/gep-alias.ll @@ -14,7 +14,7 @@ target triple = "x86_64-unknown-linux-gnu" define ptr @f() { ; CHECK-LABEL: define ptr @f() { -; CHECK-NEXT: ret ptr getelementptr ([3 x ptr], ptr @b, i64 0, i64 1) +; CHECK-NEXT: ret ptr getelementptr (i8, ptr @b, i64 8) ; ret ptr getelementptr ([3 x ptr], ptr @b, i64 0, i64 1) } diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/gep-constanfolding-error.ll b/llvm/test/Transforms/InstSimplify/ConstProp/gep-constanfolding-error.ll index bcba5ce3aa7e..e5287a45da4b 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/gep-constanfolding-error.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/gep-constanfolding-error.ll @@ -44,8 +44,7 @@ entry: %9 = add i32 %f.promoted, %smax %10 = add i32 %9, 2 call void @llvm.memset.p0.i32(ptr %scevgep, i8 %conv6, i32 %10, i1 false) -; CHECK: call void @llvm.memset.p0.i32(ptr getelementptr inbounds ([6 x [6 x [7 x i8]]], ptr @j, i32 0, i{{32|64}} 5, i{{32|64}} 4, i32 1), i8 %conv6, i32 1, i1 false) -; CHECK-NOT: call void @llvm.memset.p0.i32(ptr getelementptr ([6 x [6 x [7 x i8]]], ptr @j, i64 1, i64 4, i64 4, i32 1) +; CHECK: call void @llvm.memset.p0.i32(ptr getelementptr inbounds (i8, ptr @j, i32 239), i8 %conv6, i32 1, i1 false) ret i32 0 } ; Function Attrs: argmemonly nounwind diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/gep.ll b/llvm/test/Transforms/InstSimplify/ConstProp/gep.ll index d91349a570b7..b3fe7f36ff97 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/gep.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/gep.ll @@ -11,21 +11,21 @@ target triple = "x86_64-unknown-linux-gnu" define ptr @f0() { ; CHECK-LABEL: @f0( -; CHECK-NEXT: ret ptr getelementptr inbounds inrange(-16, 8) ([3 x ptr], ptr @vt, i64 0, i64 2) +; CHECK-NEXT: ret ptr getelementptr inbounds inrange(-16, 8) (i8, ptr @vt, i64 16) ; ret ptr getelementptr (ptr, ptr getelementptr inbounds inrange(-8, 16) ([3 x ptr], ptr @vt, i64 0, i64 1), i64 1) } define ptr @f1() { ; CHECK-LABEL: @f1( -; CHECK-NEXT: ret ptr getelementptr inbounds inrange(-8, 0) ([3 x ptr], ptr @vt, i64 0, i64 2) +; CHECK-NEXT: ret ptr getelementptr inbounds inrange(-8, 0) (i8, ptr @vt, i64 16) ; ret ptr getelementptr (ptr, ptr getelementptr inbounds inrange(0, 8) ([3 x ptr], ptr @vt, i64 0, i64 1), i64 1) } define ptr @f2() { ; CHECK-LABEL: @f2( -; CHECK-NEXT: ret ptr getelementptr inrange(-24, -16) ([3 x ptr], ptr @vt, i64 1, i64 1) +; CHECK-NEXT: ret ptr getelementptr inrange(-24, -16) (i8, ptr @vt, i64 32) ; ret ptr getelementptr (ptr, ptr getelementptr inbounds inrange(0, 8) ([3 x ptr], ptr @vt, i64 0, i64 1), i64 3) } diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/icmp-global.ll b/llvm/test/Transforms/InstSimplify/ConstProp/icmp-global.ll index b4afb7bd4a2b..1d7ed23d3e82 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/icmp-global.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/icmp-global.ll @@ -121,7 +121,7 @@ define i1 @global_gep_ugt_null() { define i1 @global_gep_sgt_null() { ; CHECK-LABEL: @global_gep_sgt_null( -; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr inbounds ([2 x i32], ptr @g, i64 1), ptr null) +; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr inbounds (i8, ptr @g, i64 8), ptr null) ; %gep = getelementptr inbounds [2 x i32], ptr @g, i64 1 %cmp = icmp sgt ptr %gep, null @@ -222,7 +222,7 @@ define i1 @global_gep_ugt_global() { define i1 @global_gep_sgt_global() { ; CHECK-LABEL: @global_gep_sgt_global( -; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr inbounds ([2 x i32], ptr @g, i64 1), ptr @g) +; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr inbounds (i8, ptr @g, i64 8), ptr @g) ; %gep = getelementptr inbounds [2 x i32], ptr @g, i64 1 %cmp = icmp sgt ptr %gep, @g @@ -232,7 +232,7 @@ define i1 @global_gep_sgt_global() { ; This should not fold to true, as the offset is negative. define i1 @global_gep_ugt_global_neg_offset() { ; CHECK-LABEL: @global_gep_ugt_global_neg_offset( -; CHECK-NEXT: ret i1 icmp ugt (ptr getelementptr ([2 x i32], ptr @g, i64 -1), ptr @g) +; CHECK-NEXT: ret i1 icmp ugt (ptr getelementptr (i8, ptr @g, i64 -8), ptr @g) ; %gep = getelementptr [2 x i32], ptr @g, i64 -1 %cmp = icmp ugt ptr %gep, @g @@ -241,7 +241,7 @@ define i1 @global_gep_ugt_global_neg_offset() { define i1 @global_gep_sgt_global_neg_offset() { ; CHECK-LABEL: @global_gep_sgt_global_neg_offset( -; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr ([2 x i32], ptr @g, i64 -1), ptr @g) +; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr (i8, ptr @g, i64 -8), ptr @g) ; %gep = getelementptr [2 x i32], ptr @g, i64 -1 %cmp = icmp sgt ptr %gep, @g @@ -260,7 +260,7 @@ define i1 @global_gep_ugt_global_gep() { ; Should not fold due to signed comparison. define i1 @global_gep_sgt_global_gep() { ; CHECK-LABEL: @global_gep_sgt_global_gep( -; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr inbounds ([2 x i32], ptr @g, i64 0, i64 1), ptr @g) +; CHECK-NEXT: ret i1 icmp sgt (ptr getelementptr inbounds (i8, ptr @g, i64 4), ptr @g) ; %gep2 = getelementptr inbounds [2 x i32], ptr @g, i64 0, i64 1 %cmp = icmp sgt ptr %gep2, @g diff --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll index 724912d90bd8..0f72cd813f2f 100644 --- a/llvm/test/Transforms/InstSimplify/compare.ll +++ b/llvm/test/Transforms/InstSimplify/compare.ll @@ -3078,7 +3078,7 @@ define i1 @globals_inequal() { ; TODO: Never equal define i1 @globals_offset_inequal() { ; CHECK-LABEL: @globals_offset_inequal( -; CHECK-NEXT: ret i1 icmp ne (ptr getelementptr (i8, ptr @A, i32 1), ptr getelementptr (i8, ptr @B, i32 1)) +; CHECK-NEXT: ret i1 icmp ne (ptr getelementptr inbounds (i8, ptr @A, i32 1), ptr getelementptr inbounds (i8, ptr @B, i32 1)) ; %a.off = getelementptr i8, ptr @A, i32 1 %b.off = getelementptr i8, ptr @B, i32 1 diff --git a/llvm/test/Transforms/InstSimplify/past-the-end.ll b/llvm/test/Transforms/InstSimplify/past-the-end.ll index 96339c1cdcf2..1e146d18327a 100644 --- a/llvm/test/Transforms/InstSimplify/past-the-end.ll +++ b/llvm/test/Transforms/InstSimplify/past-the-end.ll @@ -21,7 +21,7 @@ define zeroext i1 @no_offsets() { define zeroext i1 @both_past_the_end() { ; CHECK-LABEL: @both_past_the_end( -; CHECK-NEXT: ret i1 icmp eq (ptr getelementptr inbounds (i32, ptr @opte_a, i32 1), ptr getelementptr inbounds (i32, ptr @opte_b, i32 1)) +; CHECK-NEXT: ret i1 icmp eq (ptr getelementptr inbounds (i8, ptr @opte_a, i32 4), ptr getelementptr inbounds (i8, ptr @opte_b, i32 4)) ; %x = getelementptr i32, ptr @opte_a, i32 1 %y = getelementptr i32, ptr @opte_b, i32 1 @@ -35,7 +35,7 @@ define zeroext i1 @both_past_the_end() { define zeroext i1 @just_one_past_the_end() { ; CHECK-LABEL: @just_one_past_the_end( -; CHECK-NEXT: ret i1 icmp eq (ptr getelementptr inbounds (i32, ptr @opte_a, i32 1), ptr @opte_b) +; CHECK-NEXT: ret i1 icmp eq (ptr getelementptr inbounds (i8, ptr @opte_a, i32 4), ptr @opte_b) ; %x = getelementptr i32, ptr @opte_a, i32 1 %t = icmp eq ptr %x, @opte_b diff --git a/llvm/test/Transforms/LoopStrengthReduce/2011-12-19-PostincQuadratic.ll b/llvm/test/Transforms/LoopStrengthReduce/2011-12-19-PostincQuadratic.ll index 552cd8803732..616e3ae1b036 100644 --- a/llvm/test/Transforms/LoopStrengthReduce/2011-12-19-PostincQuadratic.ll +++ b/llvm/test/Transforms/LoopStrengthReduce/2011-12-19-PostincQuadratic.ll @@ -16,7 +16,7 @@ define void @vb() nounwind { ; CHECK-NEXT: for.cond.preheader: ; CHECK-NEXT: br label [[FOR_BODY7:%.*]] ; CHECK: for.body7: -; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[SCEVGEP:%.*]], [[FOR_BODY7]] ], [ getelementptr inbounds ([121 x i32], ptr @b, i32 0, i32 1), [[FOR_COND_PREHEADER:%.*]] ] +; CHECK-NEXT: [[LSR_IV1:%.*]] = phi ptr [ [[SCEVGEP:%.*]], [[FOR_BODY7]] ], [ getelementptr inbounds (i8, ptr @b, i32 4), [[FOR_COND_PREHEADER:%.*]] ] ; CHECK-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY7]] ], [ 8, [[FOR_COND_PREHEADER]] ] ; CHECK-NEXT: [[INDVARS_IV77:%.*]] = phi i32 [ [[INDVARS_IV_NEXT78:%.*]], [[FOR_BODY7]] ], [ 1, [[FOR_COND_PREHEADER]] ] ; CHECK-NEXT: [[INDVARS_IV_NEXT78]] = add i32 [[INDVARS_IV77]], 1 diff --git a/llvm/test/Transforms/LoopStrengthReduce/X86/2012-01-13-phielim.ll b/llvm/test/Transforms/LoopStrengthReduce/X86/2012-01-13-phielim.ll index 7fef404eaf14..c4aa6c7725d4 100644 --- a/llvm/test/Transforms/LoopStrengthReduce/X86/2012-01-13-phielim.ll +++ b/llvm/test/Transforms/LoopStrengthReduce/X86/2012-01-13-phielim.ll @@ -10,23 +10,23 @@ define i32 @test(ptr %base) nounwind uwtable ssp { ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[WHILE_BODY_LR_PH_I:%.*]] ; CHECK: while.body.lr.ph.i: -; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[BASE:%.*]], i64 16 +; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[BASE:%.*]], i64 16 ; CHECK-NEXT: br label [[WHILE_BODY_I:%.*]] ; CHECK: while.body.i: ; CHECK-NEXT: [[INDVARS_IV7_I:%.*]] = phi i64 [ 16, [[WHILE_BODY_LR_PH_I]] ], [ [[INDVARS_IV_NEXT8_I:%.*]], [[COND_TRUE29_I:%.*]] ] ; CHECK-NEXT: [[I_05_I:%.*]] = phi i64 [ 0, [[WHILE_BODY_LR_PH_I]] ], [ [[INDVARS_IV7_I]], [[COND_TRUE29_I]] ] ; CHECK-NEXT: [[LSR4:%.*]] = trunc i64 [[I_05_I]] to i32 ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[LSR4]] to i64 -; CHECK-NEXT: [[UGLYGEP1:%.*]] = getelementptr i8, ptr [[UGLYGEP]], i64 [[TMP0]] +; CHECK-NEXT: [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[SCEVGEP]], i64 [[TMP0]] ; CHECK-NEXT: [[SEXT_I:%.*]] = shl i64 [[I_05_I]], 32 ; CHECK-NEXT: [[IDX_EXT_I:%.*]] = ashr exact i64 [[SEXT_I]], 32 ; CHECK-NEXT: [[ADD_PTR_SUM_I:%.*]] = add i64 [[IDX_EXT_I]], 16 ; CHECK-NEXT: br label [[FOR_BODY_I:%.*]] ; CHECK: for.body.i: -; CHECK-NEXT: [[LSR_IV2:%.*]] = phi ptr [ [[UGLYGEP3:%.*]], [[FOR_BODY_I]] ], [ [[UGLYGEP1]], [[WHILE_BODY_I]] ] +; CHECK-NEXT: [[LSR_IV2:%.*]] = phi ptr [ [[SCEVGEP3:%.*]], [[FOR_BODY_I]] ], [ [[SCEVGEP1]], [[WHILE_BODY_I]] ] ; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[LSR_IV2]], align 1 ; CHECK-NEXT: [[CMP:%.*]] = call i1 @check() #[[ATTR3:[0-9]+]] -; CHECK-NEXT: [[UGLYGEP3]] = getelementptr i8, ptr [[LSR_IV2]], i64 1 +; CHECK-NEXT: [[SCEVGEP3]] = getelementptr i8, ptr [[LSR_IV2]], i64 1 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_END_I:%.*]], label [[FOR_BODY_I]] ; CHECK: for.end.i: ; CHECK-NEXT: [[ADD_PTR_I144:%.*]] = getelementptr inbounds i8, ptr [[BASE]], i64 [[ADD_PTR_SUM_I]] @@ -96,18 +96,18 @@ define void @test2(i32 %n) nounwind uwtable { ; CHECK-NEXT: br label [[FOR_COND468:%.*]] ; CHECK: for.cond468: ; CHECK-NEXT: [[LSR_IV1:%.*]] = phi i32 [ 1, [[FOR_COND468_PREHEADER]] ], [ [[LSR_IV_NEXT:%.*]], [[IF_THEN477:%.*]] ] -; CHECK-NEXT: [[LSR_IV:%.*]] = phi ptr [ getelementptr inbounds ([5000 x %struct.anon.7.91.199.307.415.475.559.643.751.835.943.1003.1111.1219.1351.1375.1399.1435.1471.1483.1519.1531.1651.1771], ptr @tags, i64 0, i64 0, i32 2), [[FOR_COND468_PREHEADER]] ], [ [[UGLYGEP:%.*]], [[IF_THEN477]] ] +; CHECK-NEXT: [[LSR_IV:%.*]] = phi ptr [ getelementptr inbounds (i8, ptr @tags, i64 8), [[FOR_COND468_PREHEADER]] ], [ [[SCEVGEP:%.*]], [[IF_THEN477]] ] ; CHECK-NEXT: [[K_0:%.*]] = load i32, ptr [[LSR_IV]], align 4 ; CHECK-NEXT: [[CMP469:%.*]] = icmp slt i32 [[LSR_IV1]], [[N:%.*]] ; CHECK-NEXT: br i1 [[CMP469]], label [[FOR_BODY471:%.*]], label [[FOR_INC498_PREHEADER:%.*]] ; CHECK: for.body471: -; CHECK-NEXT: [[UGLYGEP2:%.*]] = getelementptr i8, ptr [[LSR_IV]], i64 8 -; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[UGLYGEP2]], align 4 +; CHECK-NEXT: [[SCEVGEP2:%.*]] = getelementptr i8, ptr [[LSR_IV]], i64 8 +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[SCEVGEP2]], align 4 ; CHECK-NEXT: br i1 false, label [[IF_THEN477]], label [[FOR_INC498_PREHEADER]] ; CHECK: for.inc498.preheader: ; CHECK-NEXT: br label [[FOR_INC498:%.*]] ; CHECK: if.then477: -; CHECK-NEXT: [[UGLYGEP]] = getelementptr i8, ptr [[LSR_IV]], i64 12 +; CHECK-NEXT: [[SCEVGEP]] = getelementptr i8, ptr [[LSR_IV]], i64 12 ; CHECK-NEXT: [[LSR_IV_NEXT]] = add nuw nsw i32 [[LSR_IV1]], 1 ; CHECK-NEXT: br label [[FOR_COND468]] ; CHECK: for.inc498: @@ -162,8 +162,8 @@ define fastcc void @test3(ptr nocapture %u) nounwind uwtable ssp { ; CHECK-NEXT: [[TMP:%.*]] = trunc i64 [[TMP0]] to i32 ; CHECK-NEXT: [[MUL_I_US_I:%.*]] = mul nsw i32 0, [[TMP]] ; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[INDVARS_IV_I_SV_PHI]], 3 -; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, ptr [[U:%.*]], i64 [[TMP1]] -; CHECK-NEXT: [[TMP2:%.*]] = load double, ptr [[UGLYGEP]], align 8 +; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[U:%.*]], i64 [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = load double, ptr [[SCEVGEP]], align 8 ; CHECK-NEXT: br i1 undef, label [[FOR_INC8_US_I:%.*]], label [[MESHBB]] ; CHECK: for.body3.lr.ph.us.i.loopexit: ; CHECK-NEXT: [[LSR_IV_NEXT:%.*]] = add i64 [[LSR_IV]], 1 diff --git a/llvm/test/Transforms/LoopVectorize/X86/pr42674.ll b/llvm/test/Transforms/LoopVectorize/X86/pr42674.ll index 97bb4a2b4db5..1c64359dea24 100644 --- a/llvm/test/Transforms/LoopVectorize/X86/pr42674.ll +++ b/llvm/test/Transforms/LoopVectorize/X86/pr42674.ll @@ -9,7 +9,7 @@ define zeroext i8 @sum() { ; CHECK-LABEL: @sum( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[WIDE_LOAD2:%.*]] = load <64 x i8>, ptr getelementptr inbounds ([128 x i8], ptr @bytes, i64 0, i64 64), align 1 +; CHECK-NEXT: [[WIDE_LOAD2:%.*]] = load <64 x i8>, ptr getelementptr inbounds (i8, ptr @bytes, i64 64), align 1 ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <64 x i8>, ptr @bytes, align 1 ; CHECK-NEXT: [[BIN_RDX:%.*]] = add <64 x i8> [[WIDE_LOAD2]], [[WIDE_LOAD]] ; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.vector.reduce.add.v64i8(<64 x i8> [[BIN_RDX]]) diff --git a/llvm/test/Transforms/LoopVectorize/pr47343-expander-lcssa-after-cfg-update.ll b/llvm/test/Transforms/LoopVectorize/pr47343-expander-lcssa-after-cfg-update.ll index b3b6d3ee5509..aebe47c12879 100644 --- a/llvm/test/Transforms/LoopVectorize/pr47343-expander-lcssa-after-cfg-update.ll +++ b/llvm/test/Transforms/LoopVectorize/pr47343-expander-lcssa-after-cfg-update.ll @@ -39,14 +39,14 @@ define void @f() { ; CHECK: vector.memcheck: ; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[TMP1]], i64 1 ; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr @f.e, [[SCEVGEP]] -; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[TMP1]], getelementptr inbounds (i32, ptr @f.e, i64 1) +; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[TMP1]], getelementptr inbounds (i8, ptr @f.e, i64 4) ; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]] ; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: store i32 0, ptr @f.e, align 1, !alias.scope !0, !noalias !3 +; CHECK-NEXT: store i32 0, ptr @f.e, align 1, !alias.scope [[META0:![0-9]+]], !noalias [[META3:![0-9]+]] ; CHECK-NEXT: store i8 10, ptr [[TMP0]], align 1 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[INDEX_NEXT]], 500 diff --git a/llvm/test/Transforms/LoopVersioning/add-phi-update-users.ll b/llvm/test/Transforms/LoopVersioning/add-phi-update-users.ll index d9050700001a..e326064175d1 100644 --- a/llvm/test/Transforms/LoopVersioning/add-phi-update-users.ll +++ b/llvm/test/Transforms/LoopVersioning/add-phi-update-users.ll @@ -27,7 +27,7 @@ define void @f1() { ; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[T0]], i64 2 ; CHECK-NEXT: br label [[FOR_BODY_LVER_CHECK:%.*]] ; CHECK: for.body.lver.check: -; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr [[T0]], getelementptr inbounds (i16, ptr @b, i64 1) +; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr [[T0]], getelementptr inbounds (i8, ptr @b, i64 2) ; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr @b, [[SCEVGEP]] ; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]] ; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], label [[FOR_BODY_PH_LVER_ORIG:%.*]], label [[FOR_BODY_PH:%.*]] @@ -44,8 +44,8 @@ define void @f1() { ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[T1:%.*]] = phi i64 [ 0, [[FOR_BODY_PH]] ], [ [[INC:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[T2:%.*]] = load i16, ptr @b, align 1, !tbaa [[TBAA2]], !alias.scope !6 -; CHECK-NEXT: store i16 [[T2]], ptr [[T0]], align 1, !tbaa [[TBAA2]], !alias.scope !9, !noalias !6 +; CHECK-NEXT: [[T2:%.*]] = load i16, ptr @b, align 1, !tbaa [[TBAA2]], !alias.scope [[META6:![0-9]+]] +; CHECK-NEXT: store i16 [[T2]], ptr [[T0]], align 1, !tbaa [[TBAA2]], !alias.scope [[META9:![0-9]+]], !noalias [[META6]] ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[T1]], 1 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 3 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT1:%.*]] diff --git a/llvm/test/Transforms/LoopVersioning/bound-check-partially-known.ll b/llvm/test/Transforms/LoopVersioning/bound-check-partially-known.ll index 70c12a2d62ec..2fb58f5980ec 100644 --- a/llvm/test/Transforms/LoopVersioning/bound-check-partially-known.ll +++ b/llvm/test/Transforms/LoopVersioning/bound-check-partially-known.ll @@ -18,14 +18,14 @@ define void @bound_check_partially_known_1(i32 %N) { ; CHECK-NEXT: [[SCEVGEP2:%.*]] = getelementptr i8, ptr @global, i64 [[TMP2]] ; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr @global, [[SCEVGEP1]] ; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr [[SCEVGEP]], [[SCEVGEP2]] -; CHECK-NEXT: [[BOUND13:%.*]] = icmp ult ptr getelementptr inbounds ([[STRUCT_FOO:%.*]], ptr @global, i64 0, i32 1, i64 0), [[SCEVGEP1]] +; CHECK-NEXT: [[BOUND13:%.*]] = icmp ult ptr getelementptr inbounds (i8, ptr @global, i64 256000), [[SCEVGEP1]] ; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND13]] ; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], label [[LOOP_PH_LVER_ORIG:%.*]], label [[LOOP_PH:%.*]] ; CHECK: loop.ph.lver.orig: ; CHECK-NEXT: br label [[LOOP_LVER_ORIG:%.*]] ; CHECK: loop.lver.orig: ; CHECK-NEXT: [[IV_LVER_ORIG:%.*]] = phi i64 [ 0, [[LOOP_PH_LVER_ORIG]] ], [ [[IV_NEXT_LVER_ORIG:%.*]], [[LOOP_LVER_ORIG]] ] -; CHECK-NEXT: [[GEP_0_IV_LVER_ORIG:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @global, i64 0, i32 0, i64 [[IV_LVER_ORIG]] +; CHECK-NEXT: [[GEP_0_IV_LVER_ORIG:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr @global, i64 0, i32 0, i64 [[IV_LVER_ORIG]] ; CHECK-NEXT: [[L_0_LVER_ORIG:%.*]] = load double, ptr [[GEP_0_IV_LVER_ORIG]], align 8 ; CHECK-NEXT: [[GEP_1_IV_LVER_ORIG:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @global, i64 0, i32 1, i64 [[IV_LVER_ORIG]] ; CHECK-NEXT: [[L_1_LVER_ORIG:%.*]] = load double, ptr [[GEP_1_IV_LVER_ORIG]], align 8 @@ -41,13 +41,13 @@ define void @bound_check_partially_known_1(i32 %N) { ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[LOOP_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] ; CHECK-NEXT: [[GEP_0_IV:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @global, i64 0, i32 0, i64 [[IV]] -; CHECK-NEXT: [[L_0:%.*]] = load double, ptr [[GEP_0_IV]], align 8, !alias.scope !0 +; CHECK-NEXT: [[L_0:%.*]] = load double, ptr [[GEP_0_IV]], align 8, !alias.scope [[META0:![0-9]+]] ; CHECK-NEXT: [[GEP_1_IV:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @global, i64 0, i32 1, i64 [[IV]] -; CHECK-NEXT: [[L_1:%.*]] = load double, ptr [[GEP_1_IV]], align 8, !alias.scope !3 +; CHECK-NEXT: [[L_1:%.*]] = load double, ptr [[GEP_1_IV]], align 8, !alias.scope [[META3:![0-9]+]] ; CHECK-NEXT: [[ADD:%.*]] = fadd double [[L_0]], [[L_1]] ; CHECK-NEXT: [[IV_N:%.*]] = add nuw nsw i64 [[IV]], [[N_EXT]] ; CHECK-NEXT: [[GEP_0_IV_N:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr @global, i64 0, i32 0, i64 [[IV_N]] -; CHECK-NEXT: store double [[ADD]], ptr [[GEP_0_IV_N]], align 8, !alias.scope !5, !noalias !7 +; CHECK-NEXT: store double [[ADD]], ptr [[GEP_0_IV_N]], align 8, !alias.scope [[META5:![0-9]+]], !noalias [[META7:![0-9]+]] ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], [[N_EXT]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT_LOOPEXIT4:%.*]], label [[LOOP]] diff --git a/llvm/test/Transforms/NewGVN/loadforward.ll b/llvm/test/Transforms/NewGVN/loadforward.ll index 85ceafd433f4..a44a6e92b8ad 100644 --- a/llvm/test/Transforms/NewGVN/loadforward.ll +++ b/llvm/test/Transforms/NewGVN/loadforward.ll @@ -9,7 +9,7 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ;; Test that we forward the first store to the second load define i16 @bazinga() { ; CHECK-LABEL: @bazinga( -; CHECK-NEXT: [[_TMP10:%.*]] = load i16, ptr getelementptr inbounds ([[REC11:%.*]], ptr @str, i64 0, i32 1), align 2 +; CHECK-NEXT: [[_TMP10:%.*]] = load i16, ptr getelementptr inbounds (i8, ptr @str, i64 2), align 2 ; CHECK-NEXT: store i16 [[_TMP10]], ptr @str, align 2 ; CHECK-NEXT: [[_TMP15:%.*]] = icmp eq i16 [[_TMP10]], 3 ; CHECK-NEXT: [[_TMP16:%.*]] = select i1 [[_TMP15]], i16 1, i16 0 diff --git a/llvm/test/Transforms/PhaseOrdering/SystemZ/sub-xor.ll b/llvm/test/Transforms/PhaseOrdering/SystemZ/sub-xor.ll index 5fe267d62f93..43fd8bd59b8d 100644 --- a/llvm/test/Transforms/PhaseOrdering/SystemZ/sub-xor.ll +++ b/llvm/test/Transforms/PhaseOrdering/SystemZ/sub-xor.ll @@ -20,35 +20,35 @@ define dso_local zeroext i32 @foo(ptr noundef %a) #0 { ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT_7:%.*]], [[FOR_BODY4]] ] ; CHECK-NEXT: [[SUM_11:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD_7:%.*]], [[FOR_BODY4]] ] ; CHECK-NEXT: [[IDX_NEG:%.*]] = sub nsw i64 0, [[INDVARS_IV]] -; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[IDX_NEG]] +; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[IDX_NEG]] ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ADD_PTR]], align 4, !tbaa [[TBAA3:![0-9]+]] ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], [[SUM_11]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_NEG:%.*]] = xor i64 [[INDVARS_IV]], -1 -; CHECK-NEXT: [[ADD_PTR_110:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_NEG]] +; CHECK-NEXT: [[ADD_PTR_110:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_NEG]] ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ADD_PTR_110]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[ADD_111:%.*]] = add i32 [[TMP1]], [[ADD]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_112_NEG:%.*]] = sub nuw nsw i64 -2, [[INDVARS_IV]] -; CHECK-NEXT: [[ADD_PTR_217:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_112_NEG]] +; CHECK-NEXT: [[ADD_PTR_217:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_112_NEG]] ; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ADD_PTR_217]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[ADD_218:%.*]] = add i32 [[TMP2]], [[ADD_111]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_219_NEG:%.*]] = sub nuw nsw i64 -3, [[INDVARS_IV]] -; CHECK-NEXT: [[ADD_PTR_3:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_219_NEG]] +; CHECK-NEXT: [[ADD_PTR_3:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_219_NEG]] ; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ADD_PTR_3]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[ADD_3:%.*]] = add i32 [[TMP3]], [[ADD_218]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_3_NEG:%.*]] = sub nuw nsw i64 -4, [[INDVARS_IV]] -; CHECK-NEXT: [[ADD_PTR_4:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_3_NEG]] +; CHECK-NEXT: [[ADD_PTR_4:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_3_NEG]] ; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[ADD_PTR_4]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[ADD_4:%.*]] = add i32 [[TMP4]], [[ADD_3]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_4_NEG:%.*]] = sub nuw nsw i64 -5, [[INDVARS_IV]] -; CHECK-NEXT: [[ADD_PTR_5:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_4_NEG]] +; CHECK-NEXT: [[ADD_PTR_5:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_4_NEG]] ; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[ADD_PTR_5]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[ADD_5:%.*]] = add i32 [[TMP5]], [[ADD_4]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_5_NEG:%.*]] = sub nuw nsw i64 -6, [[INDVARS_IV]] -; CHECK-NEXT: [[ADD_PTR_6:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_5_NEG]] +; CHECK-NEXT: [[ADD_PTR_6:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_5_NEG]] ; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[ADD_PTR_6]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[ADD_6:%.*]] = add i32 [[TMP6]], [[ADD_5]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_6_NEG:%.*]] = sub nuw nsw i64 -7, [[INDVARS_IV]] -; CHECK-NEXT: [[ADD_PTR_7:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_6_NEG]] +; CHECK-NEXT: [[ADD_PTR_7:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_6_NEG]] ; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[ADD_PTR_7]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[ADD_7]] = add i32 [[TMP7]], [[ADD_6]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_7]] = add nuw nsw i64 [[INDVARS_IV]], 8 @@ -58,34 +58,34 @@ define dso_local zeroext i32 @foo(ptr noundef %a) #0 { ; CHECK-NEXT: [[INDVARS_IV_1:%.*]] = phi i64 [ [[INDVARS_IV_NEXT_1_7:%.*]], [[FOR_BODY4_1]] ], [ 0, [[FOR_BODY4]] ] ; CHECK-NEXT: [[SUM_11_1:%.*]] = phi i32 [ [[ADD_1_7:%.*]], [[FOR_BODY4_1]] ], [ [[ADD_7]], [[FOR_BODY4]] ] ; CHECK-NEXT: [[IDX_NEG_1:%.*]] = sub nsw i64 0, [[INDVARS_IV_1]] -; CHECK-NEXT: [[ADD_PTR_1:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[IDX_NEG_1]] +; CHECK-NEXT: [[ADD_PTR_1:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[IDX_NEG_1]] ; CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[ADD_PTR_1]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_1_NEG:%.*]] = xor i64 [[INDVARS_IV_1]], -1 -; CHECK-NEXT: [[ADD_PTR_1_1:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_1_NEG]] +; CHECK-NEXT: [[ADD_PTR_1_1:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_1_NEG]] ; CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[ADD_PTR_1_1]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[TMP10:%.*]] = add i32 [[TMP8]], [[TMP9]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_1_1_NEG:%.*]] = sub nuw nsw i64 -2, [[INDVARS_IV_1]] -; CHECK-NEXT: [[ADD_PTR_1_2:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_1_1_NEG]] +; CHECK-NEXT: [[ADD_PTR_1_2:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_1_1_NEG]] ; CHECK-NEXT: [[TMP11:%.*]] = load i32, ptr [[ADD_PTR_1_2]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[TMP12:%.*]] = add i32 [[TMP10]], [[TMP11]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_1_2_NEG:%.*]] = sub nuw nsw i64 -3, [[INDVARS_IV_1]] -; CHECK-NEXT: [[ADD_PTR_1_3:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_1_2_NEG]] +; CHECK-NEXT: [[ADD_PTR_1_3:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_1_2_NEG]] ; CHECK-NEXT: [[TMP13:%.*]] = load i32, ptr [[ADD_PTR_1_3]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[TMP14:%.*]] = add i32 [[TMP12]], [[TMP13]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_1_3_NEG:%.*]] = sub nuw nsw i64 -4, [[INDVARS_IV_1]] -; CHECK-NEXT: [[ADD_PTR_1_4:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_1_3_NEG]] +; CHECK-NEXT: [[ADD_PTR_1_4:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_1_3_NEG]] ; CHECK-NEXT: [[TMP15:%.*]] = load i32, ptr [[ADD_PTR_1_4]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[TMP16:%.*]] = add i32 [[TMP14]], [[TMP15]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_1_4_NEG:%.*]] = sub nuw nsw i64 -5, [[INDVARS_IV_1]] -; CHECK-NEXT: [[ADD_PTR_1_5:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_1_4_NEG]] +; CHECK-NEXT: [[ADD_PTR_1_5:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_1_4_NEG]] ; CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[ADD_PTR_1_5]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[TMP18:%.*]] = add i32 [[TMP16]], [[TMP17]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_1_5_NEG:%.*]] = sub nuw nsw i64 -6, [[INDVARS_IV_1]] -; CHECK-NEXT: [[ADD_PTR_1_6:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_1_5_NEG]] +; CHECK-NEXT: [[ADD_PTR_1_6:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_1_5_NEG]] ; CHECK-NEXT: [[TMP19:%.*]] = load i32, ptr [[ADD_PTR_1_6]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[TMP20:%.*]] = add i32 [[TMP18]], [[TMP19]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_1_6_NEG:%.*]] = sub nuw nsw i64 -7, [[INDVARS_IV_1]] -; CHECK-NEXT: [[ADD_PTR_1_7:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_1_6_NEG]] +; CHECK-NEXT: [[ADD_PTR_1_7:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_1_6_NEG]] ; CHECK-NEXT: [[TMP21:%.*]] = load i32, ptr [[ADD_PTR_1_7]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[TMP22:%.*]] = add i32 [[TMP20]], [[TMP21]] ; CHECK-NEXT: [[TMP23:%.*]] = shl i32 [[TMP22]], 1 @@ -97,42 +97,42 @@ define dso_local zeroext i32 @foo(ptr noundef %a) #0 { ; CHECK-NEXT: [[INDVARS_IV_2:%.*]] = phi i64 [ [[INDVARS_IV_NEXT_2_7:%.*]], [[FOR_BODY4_2]] ], [ 0, [[FOR_BODY4_1]] ] ; CHECK-NEXT: [[SUM_11_2:%.*]] = phi i32 [ [[ADD_2_7:%.*]], [[FOR_BODY4_2]] ], [ [[ADD_1_7]], [[FOR_BODY4_1]] ] ; CHECK-NEXT: [[IDX_NEG_2:%.*]] = sub nsw i64 0, [[INDVARS_IV_2]] -; CHECK-NEXT: [[ADD_PTR_2:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[IDX_NEG_2]] +; CHECK-NEXT: [[ADD_PTR_2:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[IDX_NEG_2]] ; CHECK-NEXT: [[TMP24:%.*]] = load i32, ptr [[ADD_PTR_2]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[MUL_2:%.*]] = mul i32 [[TMP24]], 3 ; CHECK-NEXT: [[ADD_2:%.*]] = add i32 [[MUL_2]], [[SUM_11_2]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_2_NEG:%.*]] = xor i64 [[INDVARS_IV_2]], -1 -; CHECK-NEXT: [[ADD_PTR_2_1:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_2_NEG]] +; CHECK-NEXT: [[ADD_PTR_2_1:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_2_NEG]] ; CHECK-NEXT: [[TMP25:%.*]] = load i32, ptr [[ADD_PTR_2_1]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[MUL_2_1:%.*]] = mul i32 [[TMP25]], 3 ; CHECK-NEXT: [[ADD_2_1:%.*]] = add i32 [[MUL_2_1]], [[ADD_2]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_2_1_NEG:%.*]] = sub nuw nsw i64 -2, [[INDVARS_IV_2]] -; CHECK-NEXT: [[ADD_PTR_2_2:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_2_1_NEG]] +; CHECK-NEXT: [[ADD_PTR_2_2:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_2_1_NEG]] ; CHECK-NEXT: [[TMP26:%.*]] = load i32, ptr [[ADD_PTR_2_2]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[MUL_2_2:%.*]] = mul i32 [[TMP26]], 3 ; CHECK-NEXT: [[ADD_2_2:%.*]] = add i32 [[MUL_2_2]], [[ADD_2_1]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_2_2_NEG:%.*]] = sub nuw nsw i64 -3, [[INDVARS_IV_2]] -; CHECK-NEXT: [[ADD_PTR_2_3:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_2_2_NEG]] +; CHECK-NEXT: [[ADD_PTR_2_3:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_2_2_NEG]] ; CHECK-NEXT: [[TMP27:%.*]] = load i32, ptr [[ADD_PTR_2_3]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[MUL_2_3:%.*]] = mul i32 [[TMP27]], 3 ; CHECK-NEXT: [[ADD_2_3:%.*]] = add i32 [[MUL_2_3]], [[ADD_2_2]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_2_3_NEG:%.*]] = sub nuw nsw i64 -4, [[INDVARS_IV_2]] -; CHECK-NEXT: [[ADD_PTR_2_4:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_2_3_NEG]] +; CHECK-NEXT: [[ADD_PTR_2_4:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_2_3_NEG]] ; CHECK-NEXT: [[TMP28:%.*]] = load i32, ptr [[ADD_PTR_2_4]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[MUL_2_4:%.*]] = mul i32 [[TMP28]], 3 ; CHECK-NEXT: [[ADD_2_4:%.*]] = add i32 [[MUL_2_4]], [[ADD_2_3]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_2_4_NEG:%.*]] = sub nuw nsw i64 -5, [[INDVARS_IV_2]] -; CHECK-NEXT: [[ADD_PTR_2_5:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_2_4_NEG]] +; CHECK-NEXT: [[ADD_PTR_2_5:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_2_4_NEG]] ; CHECK-NEXT: [[TMP29:%.*]] = load i32, ptr [[ADD_PTR_2_5]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[MUL_2_5:%.*]] = mul i32 [[TMP29]], 3 ; CHECK-NEXT: [[ADD_2_5:%.*]] = add i32 [[MUL_2_5]], [[ADD_2_4]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_2_5_NEG:%.*]] = sub nuw nsw i64 -6, [[INDVARS_IV_2]] -; CHECK-NEXT: [[ADD_PTR_2_6:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_2_5_NEG]] +; CHECK-NEXT: [[ADD_PTR_2_6:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_2_5_NEG]] ; CHECK-NEXT: [[TMP30:%.*]] = load i32, ptr [[ADD_PTR_2_6]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[MUL_2_6:%.*]] = mul i32 [[TMP30]], 3 ; CHECK-NEXT: [[ADD_2_6:%.*]] = add i32 [[MUL_2_6]], [[ADD_2_5]] ; CHECK-NEXT: [[INDVARS_IV_NEXT_2_6_NEG:%.*]] = sub nuw nsw i64 -7, [[INDVARS_IV_2]] -; CHECK-NEXT: [[ADD_PTR_2_7:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds ([100 x i32], ptr @ARR, i64 0, i64 99), i64 [[INDVARS_IV_NEXT_2_6_NEG]] +; CHECK-NEXT: [[ADD_PTR_2_7:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds (i8, ptr @ARR, i64 396), i64 [[INDVARS_IV_NEXT_2_6_NEG]] ; CHECK-NEXT: [[TMP31:%.*]] = load i32, ptr [[ADD_PTR_2_7]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[MUL_2_7:%.*]] = mul i32 [[TMP31]], 3 ; CHECK-NEXT: [[ADD_2_7]] = add i32 [[MUL_2_7]], [[ADD_2_6]] diff --git a/llvm/test/Transforms/PhaseOrdering/X86/excessive-unrolling.ll b/llvm/test/Transforms/PhaseOrdering/X86/excessive-unrolling.ll index 741e3ad4f7b9..ed25734c8448 100644 --- a/llvm/test/Transforms/PhaseOrdering/X86/excessive-unrolling.ll +++ b/llvm/test/Transforms/PhaseOrdering/X86/excessive-unrolling.ll @@ -13,129 +13,129 @@ define void @test_known_trip_count() { ; CHECK-LABEL: @test_known_trip_count( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x double>, ptr @b, align 16 -; CHECK-NEXT: [[WIDE_LOAD3:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 2), align 16 +; CHECK-NEXT: [[WIDE_LOAD3:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 16), align 16 ; CHECK-NEXT: [[WIDE_LOAD4:%.*]] = load <2 x double>, ptr @c, align 16 -; CHECK-NEXT: [[WIDE_LOAD5:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 2), align 16 +; CHECK-NEXT: [[WIDE_LOAD5:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 16), align 16 ; CHECK-NEXT: [[TMP0:%.*]] = fadd <2 x double> [[WIDE_LOAD]], [[WIDE_LOAD4]] ; CHECK-NEXT: [[TMP1:%.*]] = fadd <2 x double> [[WIDE_LOAD3]], [[WIDE_LOAD5]] ; CHECK-NEXT: store <2 x double> [[TMP0]], ptr @a, align 16 -; CHECK-NEXT: store <2 x double> [[TMP1]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 2), align 16 -; CHECK-NEXT: [[WIDE_LOAD_1:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 4), align 16 -; CHECK-NEXT: [[WIDE_LOAD3_1:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 6), align 16 -; CHECK-NEXT: [[WIDE_LOAD4_1:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 4), align 16 -; CHECK-NEXT: [[WIDE_LOAD5_1:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 6), align 16 +; CHECK-NEXT: store <2 x double> [[TMP1]], ptr getelementptr inbounds (i8, ptr @a, i64 16), align 16 +; CHECK-NEXT: [[WIDE_LOAD_1:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 32), align 16 +; CHECK-NEXT: [[WIDE_LOAD3_1:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 48), align 16 +; CHECK-NEXT: [[WIDE_LOAD4_1:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 32), align 16 +; CHECK-NEXT: [[WIDE_LOAD5_1:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 48), align 16 ; CHECK-NEXT: [[TMP2:%.*]] = fadd <2 x double> [[WIDE_LOAD_1]], [[WIDE_LOAD4_1]] ; CHECK-NEXT: [[TMP3:%.*]] = fadd <2 x double> [[WIDE_LOAD3_1]], [[WIDE_LOAD5_1]] -; CHECK-NEXT: store <2 x double> [[TMP2]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 4), align 16 -; CHECK-NEXT: store <2 x double> [[TMP3]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 6), align 16 -; CHECK-NEXT: [[WIDE_LOAD_2:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 8), align 16 -; CHECK-NEXT: [[WIDE_LOAD3_2:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 10), align 16 -; CHECK-NEXT: [[WIDE_LOAD4_2:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 8), align 16 -; CHECK-NEXT: [[WIDE_LOAD5_2:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 10), align 16 +; CHECK-NEXT: store <2 x double> [[TMP2]], ptr getelementptr inbounds (i8, ptr @a, i64 32), align 16 +; CHECK-NEXT: store <2 x double> [[TMP3]], ptr getelementptr inbounds (i8, ptr @a, i64 48), align 16 +; CHECK-NEXT: [[WIDE_LOAD_2:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 64), align 16 +; CHECK-NEXT: [[WIDE_LOAD3_2:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 80), align 16 +; CHECK-NEXT: [[WIDE_LOAD4_2:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 64), align 16 +; CHECK-NEXT: [[WIDE_LOAD5_2:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 80), align 16 ; CHECK-NEXT: [[TMP4:%.*]] = fadd <2 x double> [[WIDE_LOAD_2]], [[WIDE_LOAD4_2]] ; CHECK-NEXT: [[TMP5:%.*]] = fadd <2 x double> [[WIDE_LOAD3_2]], [[WIDE_LOAD5_2]] -; CHECK-NEXT: store <2 x double> [[TMP4]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 8), align 16 -; CHECK-NEXT: store <2 x double> [[TMP5]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 10), align 16 -; CHECK-NEXT: [[WIDE_LOAD_3:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 12), align 16 -; CHECK-NEXT: [[WIDE_LOAD3_3:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 14), align 16 -; CHECK-NEXT: [[WIDE_LOAD4_3:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 12), align 16 -; CHECK-NEXT: [[WIDE_LOAD5_3:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 14), align 16 +; CHECK-NEXT: store <2 x double> [[TMP4]], ptr getelementptr inbounds (i8, ptr @a, i64 64), align 16 +; CHECK-NEXT: store <2 x double> [[TMP5]], ptr getelementptr inbounds (i8, ptr @a, i64 80), align 16 +; CHECK-NEXT: [[WIDE_LOAD_3:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 96), align 16 +; CHECK-NEXT: [[WIDE_LOAD3_3:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 112), align 16 +; CHECK-NEXT: [[WIDE_LOAD4_3:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 96), align 16 +; CHECK-NEXT: [[WIDE_LOAD5_3:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 112), align 16 ; CHECK-NEXT: [[TMP6:%.*]] = fadd <2 x double> [[WIDE_LOAD_3]], [[WIDE_LOAD4_3]] ; CHECK-NEXT: [[TMP7:%.*]] = fadd <2 x double> [[WIDE_LOAD3_3]], [[WIDE_LOAD5_3]] -; CHECK-NEXT: store <2 x double> [[TMP6]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 12), align 16 -; CHECK-NEXT: store <2 x double> [[TMP7]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 14), align 16 -; CHECK-NEXT: [[WIDE_LOAD_4:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 16), align 16 -; CHECK-NEXT: [[WIDE_LOAD3_4:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 18), align 16 -; CHECK-NEXT: [[WIDE_LOAD4_4:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 16), align 16 -; CHECK-NEXT: [[WIDE_LOAD5_4:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 18), align 16 +; CHECK-NEXT: store <2 x double> [[TMP6]], ptr getelementptr inbounds (i8, ptr @a, i64 96), align 16 +; CHECK-NEXT: store <2 x double> [[TMP7]], ptr getelementptr inbounds (i8, ptr @a, i64 112), align 16 +; CHECK-NEXT: [[WIDE_LOAD_4:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 128), align 16 +; CHECK-NEXT: [[WIDE_LOAD3_4:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 144), align 16 +; CHECK-NEXT: [[WIDE_LOAD4_4:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 128), align 16 +; CHECK-NEXT: [[WIDE_LOAD5_4:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 144), align 16 ; CHECK-NEXT: [[TMP8:%.*]] = fadd <2 x double> [[WIDE_LOAD_4]], [[WIDE_LOAD4_4]] ; CHECK-NEXT: [[TMP9:%.*]] = fadd <2 x double> [[WIDE_LOAD3_4]], [[WIDE_LOAD5_4]] -; CHECK-NEXT: store <2 x double> [[TMP8]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 16), align 16 -; CHECK-NEXT: store <2 x double> [[TMP9]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 18), align 16 -; CHECK-NEXT: [[WIDE_LOAD_5:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 20), align 16 -; CHECK-NEXT: [[WIDE_LOAD3_5:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 22), align 16 -; CHECK-NEXT: [[WIDE_LOAD4_5:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 20), align 16 -; CHECK-NEXT: [[WIDE_LOAD5_5:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 22), align 16 +; CHECK-NEXT: store <2 x double> [[TMP8]], ptr getelementptr inbounds (i8, ptr @a, i64 128), align 16 +; CHECK-NEXT: store <2 x double> [[TMP9]], ptr getelementptr inbounds (i8, ptr @a, i64 144), align 16 +; CHECK-NEXT: [[WIDE_LOAD_5:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 160), align 16 +; CHECK-NEXT: [[WIDE_LOAD3_5:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 176), align 16 +; CHECK-NEXT: [[WIDE_LOAD4_5:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 160), align 16 +; CHECK-NEXT: [[WIDE_LOAD5_5:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 176), align 16 ; CHECK-NEXT: [[TMP10:%.*]] = fadd <2 x double> [[WIDE_LOAD_5]], [[WIDE_LOAD4_5]] ; CHECK-NEXT: [[TMP11:%.*]] = fadd <2 x double> [[WIDE_LOAD3_5]], [[WIDE_LOAD5_5]] -; CHECK-NEXT: store <2 x double> [[TMP10]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 20), align 16 -; CHECK-NEXT: store <2 x double> [[TMP11]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 22), align 16 -; CHECK-NEXT: [[WIDE_LOAD_6:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 24), align 16 -; CHECK-NEXT: [[WIDE_LOAD3_6:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 26), align 16 -; CHECK-NEXT: [[WIDE_LOAD4_6:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 24), align 16 -; CHECK-NEXT: [[WIDE_LOAD5_6:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 26), align 16 +; CHECK-NEXT: store <2 x double> [[TMP10]], ptr getelementptr inbounds (i8, ptr @a, i64 160), align 16 +; CHECK-NEXT: store <2 x double> [[TMP11]], ptr getelementptr inbounds (i8, ptr @a, i64 176), align 16 +; CHECK-NEXT: [[WIDE_LOAD_6:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 192), align 16 +; CHECK-NEXT: [[WIDE_LOAD3_6:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 208), align 16 +; CHECK-NEXT: [[WIDE_LOAD4_6:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 192), align 16 +; CHECK-NEXT: [[WIDE_LOAD5_6:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 208), align 16 ; CHECK-NEXT: [[TMP12:%.*]] = fadd <2 x double> [[WIDE_LOAD_6]], [[WIDE_LOAD4_6]] ; CHECK-NEXT: [[TMP13:%.*]] = fadd <2 x double> [[WIDE_LOAD3_6]], [[WIDE_LOAD5_6]] -; CHECK-NEXT: store <2 x double> [[TMP12]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 24), align 16 -; CHECK-NEXT: store <2 x double> [[TMP13]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 26), align 16 -; CHECK-NEXT: [[WIDE_LOAD_7:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 28), align 16 -; CHECK-NEXT: [[WIDE_LOAD3_7:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 30), align 16 -; CHECK-NEXT: [[WIDE_LOAD4_7:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 28), align 16 -; CHECK-NEXT: [[WIDE_LOAD5_7:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 30), align 16 +; CHECK-NEXT: store <2 x double> [[TMP12]], ptr getelementptr inbounds (i8, ptr @a, i64 192), align 16 +; CHECK-NEXT: store <2 x double> [[TMP13]], ptr getelementptr inbounds (i8, ptr @a, i64 208), align 16 +; CHECK-NEXT: [[WIDE_LOAD_7:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 224), align 16 +; CHECK-NEXT: [[WIDE_LOAD3_7:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 240), align 16 +; CHECK-NEXT: [[WIDE_LOAD4_7:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 224), align 16 +; CHECK-NEXT: [[WIDE_LOAD5_7:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 240), align 16 ; CHECK-NEXT: [[TMP14:%.*]] = fadd <2 x double> [[WIDE_LOAD_7]], [[WIDE_LOAD4_7]] ; CHECK-NEXT: [[TMP15:%.*]] = fadd <2 x double> [[WIDE_LOAD3_7]], [[WIDE_LOAD5_7]] -; CHECK-NEXT: store <2 x double> [[TMP14]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 28), align 16 -; CHECK-NEXT: store <2 x double> [[TMP15]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 30), align 16 -; CHECK-NEXT: [[WIDE_LOAD_8:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 32), align 16 -; CHECK-NEXT: [[WIDE_LOAD3_8:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 34), align 16 -; CHECK-NEXT: [[WIDE_LOAD4_8:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 32), align 16 -; CHECK-NEXT: [[WIDE_LOAD5_8:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 34), align 16 +; CHECK-NEXT: store <2 x double> [[TMP14]], ptr getelementptr inbounds (i8, ptr @a, i64 224), align 16 +; CHECK-NEXT: store <2 x double> [[TMP15]], ptr getelementptr inbounds (i8, ptr @a, i64 240), align 16 +; CHECK-NEXT: [[WIDE_LOAD_8:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 256), align 16 +; CHECK-NEXT: [[WIDE_LOAD3_8:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 272), align 16 +; CHECK-NEXT: [[WIDE_LOAD4_8:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 256), align 16 +; CHECK-NEXT: [[WIDE_LOAD5_8:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 272), align 16 ; CHECK-NEXT: [[TMP16:%.*]] = fadd <2 x double> [[WIDE_LOAD_8]], [[WIDE_LOAD4_8]] ; CHECK-NEXT: [[TMP17:%.*]] = fadd <2 x double> [[WIDE_LOAD3_8]], [[WIDE_LOAD5_8]] -; CHECK-NEXT: store <2 x double> [[TMP16]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 32), align 16 -; CHECK-NEXT: store <2 x double> [[TMP17]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 34), align 16 -; CHECK-NEXT: [[WIDE_LOAD_9:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 36), align 16 -; CHECK-NEXT: [[WIDE_LOAD3_9:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 38), align 16 -; CHECK-NEXT: [[WIDE_LOAD4_9:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 36), align 16 -; CHECK-NEXT: [[WIDE_LOAD5_9:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 38), align 16 +; CHECK-NEXT: store <2 x double> [[TMP16]], ptr getelementptr inbounds (i8, ptr @a, i64 256), align 16 +; CHECK-NEXT: store <2 x double> [[TMP17]], ptr getelementptr inbounds (i8, ptr @a, i64 272), align 16 +; CHECK-NEXT: [[WIDE_LOAD_9:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 288), align 16 +; CHECK-NEXT: [[WIDE_LOAD3_9:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 304), align 16 +; CHECK-NEXT: [[WIDE_LOAD4_9:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 288), align 16 +; CHECK-NEXT: [[WIDE_LOAD5_9:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 304), align 16 ; CHECK-NEXT: [[TMP18:%.*]] = fadd <2 x double> [[WIDE_LOAD_9]], [[WIDE_LOAD4_9]] ; CHECK-NEXT: [[TMP19:%.*]] = fadd <2 x double> [[WIDE_LOAD3_9]], [[WIDE_LOAD5_9]] -; CHECK-NEXT: store <2 x double> [[TMP18]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 36), align 16 -; CHECK-NEXT: store <2 x double> [[TMP19]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 38), align 16 -; CHECK-NEXT: [[WIDE_LOAD_10:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 40), align 16 -; CHECK-NEXT: [[WIDE_LOAD3_10:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 42), align 16 -; CHECK-NEXT: [[WIDE_LOAD4_10:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 40), align 16 -; CHECK-NEXT: [[WIDE_LOAD5_10:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 42), align 16 +; CHECK-NEXT: store <2 x double> [[TMP18]], ptr getelementptr inbounds (i8, ptr @a, i64 288), align 16 +; CHECK-NEXT: store <2 x double> [[TMP19]], ptr getelementptr inbounds (i8, ptr @a, i64 304), align 16 +; CHECK-NEXT: [[WIDE_LOAD_10:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 320), align 16 +; CHECK-NEXT: [[WIDE_LOAD3_10:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 336), align 16 +; CHECK-NEXT: [[WIDE_LOAD4_10:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 320), align 16 +; CHECK-NEXT: [[WIDE_LOAD5_10:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 336), align 16 ; CHECK-NEXT: [[TMP20:%.*]] = fadd <2 x double> [[WIDE_LOAD_10]], [[WIDE_LOAD4_10]] ; CHECK-NEXT: [[TMP21:%.*]] = fadd <2 x double> [[WIDE_LOAD3_10]], [[WIDE_LOAD5_10]] -; CHECK-NEXT: store <2 x double> [[TMP20]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 40), align 16 -; CHECK-NEXT: store <2 x double> [[TMP21]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 42), align 16 -; CHECK-NEXT: [[WIDE_LOAD_11:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 44), align 16 -; CHECK-NEXT: [[WIDE_LOAD3_11:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 46), align 16 -; CHECK-NEXT: [[WIDE_LOAD4_11:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 44), align 16 -; CHECK-NEXT: [[WIDE_LOAD5_11:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 46), align 16 +; CHECK-NEXT: store <2 x double> [[TMP20]], ptr getelementptr inbounds (i8, ptr @a, i64 320), align 16 +; CHECK-NEXT: store <2 x double> [[TMP21]], ptr getelementptr inbounds (i8, ptr @a, i64 336), align 16 +; CHECK-NEXT: [[WIDE_LOAD_11:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 352), align 16 +; CHECK-NEXT: [[WIDE_LOAD3_11:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 368), align 16 +; CHECK-NEXT: [[WIDE_LOAD4_11:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 352), align 16 +; CHECK-NEXT: [[WIDE_LOAD5_11:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 368), align 16 ; CHECK-NEXT: [[TMP22:%.*]] = fadd <2 x double> [[WIDE_LOAD_11]], [[WIDE_LOAD4_11]] ; CHECK-NEXT: [[TMP23:%.*]] = fadd <2 x double> [[WIDE_LOAD3_11]], [[WIDE_LOAD5_11]] -; CHECK-NEXT: store <2 x double> [[TMP22]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 44), align 16 -; CHECK-NEXT: store <2 x double> [[TMP23]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 46), align 16 -; CHECK-NEXT: [[WIDE_LOAD_12:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 48), align 16 -; CHECK-NEXT: [[WIDE_LOAD3_12:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 50), align 16 -; CHECK-NEXT: [[WIDE_LOAD4_12:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 48), align 16 -; CHECK-NEXT: [[WIDE_LOAD5_12:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 50), align 16 +; CHECK-NEXT: store <2 x double> [[TMP22]], ptr getelementptr inbounds (i8, ptr @a, i64 352), align 16 +; CHECK-NEXT: store <2 x double> [[TMP23]], ptr getelementptr inbounds (i8, ptr @a, i64 368), align 16 +; CHECK-NEXT: [[WIDE_LOAD_12:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 384), align 16 +; CHECK-NEXT: [[WIDE_LOAD3_12:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 400), align 16 +; CHECK-NEXT: [[WIDE_LOAD4_12:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 384), align 16 +; CHECK-NEXT: [[WIDE_LOAD5_12:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 400), align 16 ; CHECK-NEXT: [[TMP24:%.*]] = fadd <2 x double> [[WIDE_LOAD_12]], [[WIDE_LOAD4_12]] ; CHECK-NEXT: [[TMP25:%.*]] = fadd <2 x double> [[WIDE_LOAD3_12]], [[WIDE_LOAD5_12]] -; CHECK-NEXT: store <2 x double> [[TMP24]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 48), align 16 -; CHECK-NEXT: store <2 x double> [[TMP25]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 50), align 16 -; CHECK-NEXT: [[WIDE_LOAD_13:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 52), align 16 -; CHECK-NEXT: [[WIDE_LOAD3_13:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 54), align 16 -; CHECK-NEXT: [[WIDE_LOAD4_13:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 52), align 16 -; CHECK-NEXT: [[WIDE_LOAD5_13:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 54), align 16 +; CHECK-NEXT: store <2 x double> [[TMP24]], ptr getelementptr inbounds (i8, ptr @a, i64 384), align 16 +; CHECK-NEXT: store <2 x double> [[TMP25]], ptr getelementptr inbounds (i8, ptr @a, i64 400), align 16 +; CHECK-NEXT: [[WIDE_LOAD_13:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 416), align 16 +; CHECK-NEXT: [[WIDE_LOAD3_13:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 432), align 16 +; CHECK-NEXT: [[WIDE_LOAD4_13:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 416), align 16 +; CHECK-NEXT: [[WIDE_LOAD5_13:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 432), align 16 ; CHECK-NEXT: [[TMP26:%.*]] = fadd <2 x double> [[WIDE_LOAD_13]], [[WIDE_LOAD4_13]] ; CHECK-NEXT: [[TMP27:%.*]] = fadd <2 x double> [[WIDE_LOAD3_13]], [[WIDE_LOAD5_13]] -; CHECK-NEXT: store <2 x double> [[TMP26]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 52), align 16 -; CHECK-NEXT: store <2 x double> [[TMP27]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 54), align 16 -; CHECK-NEXT: [[WIDE_LOAD_14:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 0, i64 56), align 16 -; CHECK-NEXT: [[WIDE_LOAD3_14:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @b, i64 1, i64 0), align 16 -; CHECK-NEXT: [[WIDE_LOAD4_14:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 0, i64 56), align 16 -; CHECK-NEXT: [[WIDE_LOAD5_14:%.*]] = load <2 x double>, ptr getelementptr inbounds ([58 x double], ptr @c, i64 1, i64 0), align 16 +; CHECK-NEXT: store <2 x double> [[TMP26]], ptr getelementptr inbounds (i8, ptr @a, i64 416), align 16 +; CHECK-NEXT: store <2 x double> [[TMP27]], ptr getelementptr inbounds (i8, ptr @a, i64 432), align 16 +; CHECK-NEXT: [[WIDE_LOAD_14:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 448), align 16 +; CHECK-NEXT: [[WIDE_LOAD3_14:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @b, i64 464), align 16 +; CHECK-NEXT: [[WIDE_LOAD4_14:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 448), align 16 +; CHECK-NEXT: [[WIDE_LOAD5_14:%.*]] = load <2 x double>, ptr getelementptr inbounds (i8, ptr @c, i64 464), align 16 ; CHECK-NEXT: [[TMP28:%.*]] = fadd <2 x double> [[WIDE_LOAD_14]], [[WIDE_LOAD4_14]] ; CHECK-NEXT: [[TMP29:%.*]] = fadd <2 x double> [[WIDE_LOAD3_14]], [[WIDE_LOAD5_14]] -; CHECK-NEXT: store <2 x double> [[TMP28]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 0, i64 56), align 16 -; CHECK-NEXT: store <2 x double> [[TMP29]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 1, i64 0), align 16 -; CHECK-NEXT: [[TMP30:%.*]] = load double, ptr getelementptr inbounds ([58 x double], ptr @b, i64 1, i64 2), align 16 -; CHECK-NEXT: [[TMP31:%.*]] = load double, ptr getelementptr inbounds ([58 x double], ptr @c, i64 1, i64 2), align 16 +; CHECK-NEXT: store <2 x double> [[TMP28]], ptr getelementptr inbounds (i8, ptr @a, i64 448), align 16 +; CHECK-NEXT: store <2 x double> [[TMP29]], ptr getelementptr inbounds (i8, ptr @a, i64 464), align 16 +; CHECK-NEXT: [[TMP30:%.*]] = load double, ptr getelementptr inbounds (i8, ptr @b, i64 480), align 16 +; CHECK-NEXT: [[TMP31:%.*]] = load double, ptr getelementptr inbounds (i8, ptr @c, i64 480), align 16 ; CHECK-NEXT: [[ADD:%.*]] = fadd double [[TMP30]], [[TMP31]] -; CHECK-NEXT: store double [[ADD]], ptr getelementptr inbounds ([58 x double], ptr @a, i64 1, i64 2), align 16 +; CHECK-NEXT: store double [[ADD]], ptr getelementptr inbounds (i8, ptr @a, i64 480), align 16 ; CHECK-NEXT: ret void ; entry: diff --git a/llvm/test/Transforms/SCCP/2009-09-24-byval-ptr.ll b/llvm/test/Transforms/SCCP/2009-09-24-byval-ptr.ll index 34ef4349c786..ac2e945b125b 100644 --- a/llvm/test/Transforms/SCCP/2009-09-24-byval-ptr.ll +++ b/llvm/test/Transforms/SCCP/2009-09-24-byval-ptr.ll @@ -31,7 +31,7 @@ return: ; preds = %entry define internal i32 @vfu2(ptr byval(%struct.MYstr) align 4 %u) nounwind readonly { ; CHECK-LABEL: @vfu2( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr getelementptr inbounds ([[STRUCT_MYSTR:%.*]], ptr @mystr, i64 0, i32 1), align 4 +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr getelementptr inbounds (i8, ptr @mystr, i64 4), align 4 ; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr @mystr, align 1 ; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 ; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[TMP2]], [[TMP0]] diff --git a/llvm/test/Transforms/SCCP/apint-bigint2.ll b/llvm/test/Transforms/SCCP/apint-bigint2.ll index 6092c092bea5..695d6a4cf056 100644 --- a/llvm/test/Transforms/SCCP/apint-bigint2.ll +++ b/llvm/test/Transforms/SCCP/apint-bigint2.ll @@ -23,7 +23,7 @@ define i101 @large_aggregate() { ; CHECK-LABEL: @large_aggregate( ; CHECK-NEXT: [[D:%.*]] = and i101 undef, 1 ; CHECK-NEXT: [[DD:%.*]] = or i101 [[D]], 1 -; CHECK-NEXT: [[G:%.*]] = getelementptr i101, ptr getelementptr inbounds ([6 x i101], ptr @Y, i64 0, i64 5), i101 [[DD]] +; CHECK-NEXT: [[G:%.*]] = getelementptr i101, ptr getelementptr inbounds (i8, ptr @Y, i64 80), i101 [[DD]] ; CHECK-NEXT: [[L3:%.*]] = load i101, ptr [[G]], align 4 ; CHECK-NEXT: ret i101 [[L3]] ; @@ -40,7 +40,7 @@ define i101 @large_aggregate_2() { ; CHECK-LABEL: @large_aggregate_2( ; CHECK-NEXT: [[D:%.*]] = and i101 undef, 1 ; CHECK-NEXT: [[DD:%.*]] = or i101 [[D]], 1 -; CHECK-NEXT: [[G:%.*]] = getelementptr i101, ptr getelementptr inbounds ([6 x i101], ptr @Y, i64 0, i64 5), i101 [[DD]] +; CHECK-NEXT: [[G:%.*]] = getelementptr i101, ptr getelementptr inbounds (i8, ptr @Y, i64 80), i101 [[DD]] ; CHECK-NEXT: [[L3:%.*]] = load i101, ptr [[G]], align 4 ; CHECK-NEXT: ret i101 [[L3]] ; @@ -54,7 +54,7 @@ define i101 @large_aggregate_2() { define void @index_too_large() { ; CHECK-LABEL: @index_too_large( -; CHECK-NEXT: store ptr getelementptr ([6 x i101], ptr @Y, i64 187649984473770, i64 2), ptr undef, align 8 +; CHECK-NEXT: store ptr getelementptr (i8, ptr @Y, i64 18014398509481952), ptr undef, align 8 ; CHECK-NEXT: ret void ; %ptr1 = getelementptr [6 x i101], ptr @Y, i32 0, i32 -1 diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/gather-cost.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/gather-cost.ll index 2ea472169250..45030a0965e0 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/gather-cost.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/gather-cost.ll @@ -61,16 +61,16 @@ define void @gather_load(ptr noalias %ptr) { ; CHECK-NEXT: [[ARRAYIDX183:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 4 ; CHECK-NEXT: [[ARRAYIDX184:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 6 ; CHECK-NEXT: [[ARRAYIDX185:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 8 -; CHECK-NEXT: [[L0:%.*]] = load i8, ptr getelementptr inbounds ([6 x [258 x i8]], ptr @data, i64 0, i64 1, i64 0), align 1 +; CHECK-NEXT: [[L0:%.*]] = load i8, ptr getelementptr inbounds (i8, ptr @data, i64 258), align 1 ; CHECK-NEXT: [[CONV150:%.*]] = zext i8 [[L0]] to i16 ; CHECK-NEXT: [[ADD152:%.*]] = add nuw nsw i16 [[CONV150]], 10 -; CHECK-NEXT: [[L1:%.*]] = load i8, ptr getelementptr inbounds ([6 x [258 x i8]], ptr @data, i64 0, i64 2, i64 1), align 1 +; CHECK-NEXT: [[L1:%.*]] = load i8, ptr getelementptr inbounds (i8, ptr @data, i64 517), align 1 ; CHECK-NEXT: [[CONV156:%.*]] = zext i8 [[L1]] to i16 ; CHECK-NEXT: [[ADD158:%.*]] = add nuw nsw i16 [[CONV156]], 20 -; CHECK-NEXT: [[L2:%.*]] = load i8, ptr getelementptr inbounds ([6 x [258 x i8]], ptr @data, i64 0, i64 3, i64 2), align 1 +; CHECK-NEXT: [[L2:%.*]] = load i8, ptr getelementptr inbounds (i8, ptr @data, i64 776), align 1 ; CHECK-NEXT: [[CONV162:%.*]] = zext i8 [[L2]] to i16 ; CHECK-NEXT: [[ADD164:%.*]] = add nuw nsw i16 [[CONV162]], 30 -; CHECK-NEXT: [[L3:%.*]] = load i8, ptr getelementptr inbounds ([6 x [258 x i8]], ptr @data, i64 0, i64 4, i64 3), align 1 +; CHECK-NEXT: [[L3:%.*]] = load i8, ptr getelementptr inbounds (i8, ptr @data, i64 1035), align 1 ; CHECK-NEXT: [[CONV168:%.*]] = zext i8 [[L3]] to i16 ; CHECK-NEXT: [[ADD170:%.*]] = add nuw nsw i16 [[CONV168]], 40 ; CHECK-NEXT: store i16 [[ADD152]], ptr [[ARRAYIDX182]], align 2 diff --git a/llvm/test/Transforms/SLPVectorizer/X86/pr47623.ll b/llvm/test/Transforms/SLPVectorizer/X86/pr47623.ll index c46a5aa758fb..892a2b6cee3b 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/pr47623.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/pr47623.ll @@ -13,32 +13,32 @@ define void @foo() { ; SSE-LABEL: @foo( ; SSE-NEXT: [[TMP1:%.*]] = load i32, ptr @b, align 16 ; SSE-NEXT: store i32 [[TMP1]], ptr @a, align 16 -; SSE-NEXT: [[TMP2:%.*]] = load i32, ptr getelementptr inbounds ([8 x i32], ptr @b, i64 0, i64 2), align 8 -; SSE-NEXT: store i32 [[TMP2]], ptr getelementptr inbounds ([8 x i32], ptr @a, i64 0, i64 1), align 4 -; SSE-NEXT: store i32 [[TMP1]], ptr getelementptr inbounds ([8 x i32], ptr @a, i64 0, i64 2), align 8 -; SSE-NEXT: store i32 [[TMP2]], ptr getelementptr inbounds ([8 x i32], ptr @a, i64 0, i64 3), align 4 -; SSE-NEXT: store i32 [[TMP1]], ptr getelementptr inbounds ([8 x i32], ptr @a, i64 0, i64 4), align 16 -; SSE-NEXT: store i32 [[TMP2]], ptr getelementptr inbounds ([8 x i32], ptr @a, i64 0, i64 5), align 4 -; SSE-NEXT: store i32 [[TMP1]], ptr getelementptr inbounds ([8 x i32], ptr @a, i64 0, i64 6), align 8 -; SSE-NEXT: store i32 [[TMP2]], ptr getelementptr inbounds ([8 x i32], ptr @a, i64 0, i64 7), align 4 +; SSE-NEXT: [[TMP2:%.*]] = load i32, ptr getelementptr inbounds (i8, ptr @b, i64 8), align 8 +; SSE-NEXT: store i32 [[TMP2]], ptr getelementptr inbounds (i8, ptr @a, i64 4), align 4 +; SSE-NEXT: store i32 [[TMP1]], ptr getelementptr inbounds (i8, ptr @a, i64 8), align 8 +; SSE-NEXT: store i32 [[TMP2]], ptr getelementptr inbounds (i8, ptr @a, i64 12), align 4 +; SSE-NEXT: store i32 [[TMP1]], ptr getelementptr inbounds (i8, ptr @a, i64 16), align 16 +; SSE-NEXT: store i32 [[TMP2]], ptr getelementptr inbounds (i8, ptr @a, i64 20), align 4 +; SSE-NEXT: store i32 [[TMP1]], ptr getelementptr inbounds (i8, ptr @a, i64 24), align 8 +; SSE-NEXT: store i32 [[TMP2]], ptr getelementptr inbounds (i8, ptr @a, i64 28), align 4 ; SSE-NEXT: ret void ; ; AVX-LABEL: @foo( ; AVX-NEXT: [[TMP1:%.*]] = load i32, ptr @b, align 16 -; AVX-NEXT: [[TMP2:%.*]] = load i32, ptr getelementptr inbounds ([8 x i32], ptr @b, i64 0, i64 2), align 8 +; AVX-NEXT: [[TMP2:%.*]] = load i32, ptr getelementptr inbounds (i8, ptr @b, i64 8), align 8 ; AVX-NEXT: [[TMP3:%.*]] = insertelement <8 x i32> poison, i32 [[TMP1]], i64 0 ; AVX-NEXT: [[TMP4:%.*]] = insertelement <8 x i32> [[TMP3]], i32 [[TMP2]], i64 1 -; AVX-NEXT: [[SHUFFLE:%.*]] = shufflevector <8 x i32> [[TMP4]], <8 x i32> poison, <8 x i32> -; AVX-NEXT: store <8 x i32> [[SHUFFLE]], ptr @a, align 16 +; AVX-NEXT: [[TMP5:%.*]] = shufflevector <8 x i32> [[TMP4]], <8 x i32> poison, <8 x i32> +; AVX-NEXT: store <8 x i32> [[TMP5]], ptr @a, align 16 ; AVX-NEXT: ret void ; ; AVX512-LABEL: @foo( ; AVX512-NEXT: [[TMP1:%.*]] = load i32, ptr @b, align 16 -; AVX512-NEXT: [[TMP2:%.*]] = load i32, ptr getelementptr inbounds ([8 x i32], ptr @b, i64 0, i64 2), align 8 +; AVX512-NEXT: [[TMP2:%.*]] = load i32, ptr getelementptr inbounds (i8, ptr @b, i64 8), align 8 ; AVX512-NEXT: [[TMP3:%.*]] = insertelement <8 x i32> poison, i32 [[TMP1]], i64 0 ; AVX512-NEXT: [[TMP4:%.*]] = insertelement <8 x i32> [[TMP3]], i32 [[TMP2]], i64 1 -; AVX512-NEXT: [[SHUFFLE:%.*]] = shufflevector <8 x i32> [[TMP4]], <8 x i32> poison, <8 x i32> -; AVX512-NEXT: store <8 x i32> [[SHUFFLE]], ptr @a, align 16 +; AVX512-NEXT: [[TMP5:%.*]] = shufflevector <8 x i32> [[TMP4]], <8 x i32> poison, <8 x i32> +; AVX512-NEXT: store <8 x i32> [[TMP5]], ptr @a, align 16 ; AVX512-NEXT: ret void ; %1 = load i32, ptr @b, align 16 -- GitLab From 21419071e197ca2f813a983c319a2213844dc72d Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Mon, 20 May 2024 10:47:51 +0100 Subject: [PATCH 075/793] InstSimplify: increase shufflevector test coverage (#92407) Add examples of patterns that can be simplified, but are currently not. This patch serves as a pre-commit test. --- .../Transforms/InstSimplify/shufflevector.ll | 236 +++++++++++++++++- 1 file changed, 230 insertions(+), 6 deletions(-) diff --git a/llvm/test/Transforms/InstSimplify/shufflevector.ll b/llvm/test/Transforms/InstSimplify/shufflevector.ll index 460e90aa31d9..64087194b0d1 100644 --- a/llvm/test/Transforms/InstSimplify/shufflevector.ll +++ b/llvm/test/Transforms/InstSimplify/shufflevector.ll @@ -249,13 +249,13 @@ define <8 x i64> @PR30630(<8 x i64> %x) { ; ret <2 x float> zeroinitializer define <2 x float> @PR32872(<2 x float> %x) { ; CHECK-LABEL: @PR32872( -; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> zeroinitializer, <4 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <4 x float> zeroinitializer, <4 x float> [[TMP1]], <2 x i32> -; CHECK-NEXT: ret <2 x float> [[TMP4]] +; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> zeroinitializer, <4 x i32> +; CHECK-NEXT: [[SHUF2:%.*]] = shufflevector <4 x float> zeroinitializer, <4 x float> [[SHUF]], <2 x i32> +; CHECK-NEXT: ret <2 x float> [[SHUF2]] ; - %tmp1 = shufflevector <2 x float> %x, <2 x float> zeroinitializer, <4 x i32> - %tmp4 = shufflevector <4 x float> zeroinitializer, <4 x float> %tmp1, <2 x i32> - ret <2 x float> %tmp4 + %shuf = shufflevector <2 x float> %x, <2 x float> zeroinitializer, <4 x i32> + %shuf2 = shufflevector <4 x float> zeroinitializer, <4 x float> %shuf, <2 x i32> + ret <2 x float> %shuf2 } define <5 x i8> @splat_inserted_constant(<4 x i8> %x) { @@ -284,3 +284,227 @@ define <2 x i8> @splat_inserted_constant_not_canonical(<3 x i8> %x, <3 x i8> %y) %splat2 = shufflevector <3 x i8> %y, <3 x i8> %ins2, <2 x i32> ret <2 x i8> %splat2 } + +define <4 x i32> @fold_identity(<4 x i32> %x) { +; CHECK-LABEL: @fold_identity( +; CHECK-NEXT: ret <4 x i32> [[X:%.*]] +; + %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> + %revshuf = shufflevector <4 x i32> %shuf, <4 x i32> poison, <4 x i32> + ret <4 x i32> %revshuf +} + +define <4 x i32> @fold_identity2(<4 x i32> %x) { +; CHECK-LABEL: @fold_identity2( +; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], +; CHECK-NEXT: ret <4 x i32> [[SHL]] +; + %shl = shl <4 x i32> %x, + %shuf = shufflevector <4 x i32> %shl, <4 x i32> poison, <4 x i32> + %revshuf = shufflevector <4 x i32> %shuf, <4 x i32> poison, <4 x i32> + ret <4 x i32> %revshuf +} + +define <4 x i32> @fold_identity3(<4 x i32> %x) { +; CHECK-LABEL: @fold_identity3( +; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[X]] +; CHECK-NEXT: ret <4 x i32> [[SHL]] +; + %shl = shl <4 x i32> %x, %x + %shuf = shufflevector <4 x i32> %shl, <4 x i32> poison, <4 x i32> + %revshuf = shufflevector <4 x i32> %shuf, <4 x i32> poison, <4 x i32> + ret <4 x i32> %revshuf +} + +define <4 x i32> @not_fold_identity(<4 x i32> %x) { +; CHECK-LABEL: @not_fold_identity( +; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> +; CHECK-NEXT: [[REVSHUF:%.*]] = shufflevector <4 x i32> [[SHUF]], <4 x i32> poison, <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[REVSHUF]] +; + %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> + %revshuf = shufflevector <4 x i32> %shuf, <4 x i32> poison, <4 x i32> + ret <4 x i32> %revshuf +} + +define <4 x i32> @not_fold_identity2(<4 x i32> %x) { +; CHECK-LABEL: @not_fold_identity2( +; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> +; CHECK-NEXT: [[REVSHUF:%.*]] = shufflevector <4 x i32> [[SHUF]], <4 x i32> poison, <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[REVSHUF]] +; + %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> + %revshuf = shufflevector <4 x i32> %shuf, <4 x i32> poison, <4 x i32> + ret <4 x i32> %revshuf +} + +define <4 x i64> @fold_lookthrough_cast(<4 x i32> %x) { +; CHECK-LABEL: @fold_lookthrough_cast( +; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> +; CHECK-NEXT: [[ZEXT:%.*]] = zext <4 x i32> [[SHUF]] to <4 x i64> +; CHECK-NEXT: [[REVSHUF:%.*]] = shufflevector <4 x i64> [[ZEXT]], <4 x i64> poison, <4 x i32> +; CHECK-NEXT: ret <4 x i64> [[REVSHUF]] +; + %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> + %zext = zext <4 x i32> %shuf to <4 x i64> + %revshuf = shufflevector <4 x i64> %zext, <4 x i64> poison, <4 x i32> + ret <4 x i64> %revshuf +} + +define <4 x i64> @not_fold_lookthrough_cast(<4 x i32> %x) { +; CHECK-LABEL: @not_fold_lookthrough_cast( +; CHECK-NEXT: [[ZEXT:%.*]] = zext <4 x i32> [[X:%.*]] to <4 x i64> +; CHECK-NEXT: [[REVSHUF:%.*]] = shufflevector <4 x i64> [[ZEXT]], <4 x i64> poison, <4 x i32> +; CHECK-NEXT: ret <4 x i64> [[REVSHUF]] +; + %zext = zext <4 x i32> %x to <4 x i64> + %revshuf = shufflevector <4 x i64> %zext, <4 x i64> poison, <4 x i32> + ret <4 x i64> %revshuf +} + +define <4 x i64> @not_fold_lookthrough_cast2(<4 x i32> %x) { +; CHECK-LABEL: @not_fold_lookthrough_cast2( +; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> +; CHECK-NEXT: [[ZEXT:%.*]] = zext <4 x i32> [[SHUF]] to <4 x i64> +; CHECK-NEXT: ret <4 x i64> [[ZEXT]] +; + %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> + %zext = zext <4 x i32> %shuf to <4 x i64> + ret <4 x i64> %zext +} + +define i32 @not_fold_lookthrough_bitcast(<4 x i8> %x) { +; CHECK-LABEL: @not_fold_lookthrough_bitcast( +; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> +; CHECK-NEXT: [[BITCAST:%.*]] = bitcast <4 x i8> [[SHUF]] to i32 +; CHECK-NEXT: ret i32 [[BITCAST]] +; + %shuf = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> + %bitcast = bitcast <4 x i8> %shuf to i32 + ret i32 %bitcast +} + +define <8 x i16> @not_fold_lookthrough_bitcast2(<4 x i32> %x, <8 x i16> %y) { +; CHECK-LABEL: @not_fold_lookthrough_bitcast2( +; CHECK-NEXT: [[CAST:%.*]] = bitcast <4 x i32> [[X:%.*]] to <8 x i16> +; CHECK-NEXT: [[OUT:%.*]] = shufflevector <8 x i16> [[Y:%.*]], <8 x i16> [[CAST]], <8 x i32> +; CHECK-NEXT: ret <8 x i16> [[OUT]] +; + %cast = bitcast <4 x i32> %x to <8 x i16> + %out = shufflevector <8 x i16> %y, <8 x i16> %cast, <8 x i32> + ret <8 x i16> %out +} + +define <4 x i32> @fold_lookthrough_binop_same_operands(<4 x i32> %x) { +; CHECK-LABEL: @fold_lookthrough_binop_same_operands( +; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> +; CHECK-NEXT: [[ADD:%.*]] = add <4 x i32> [[SHUF]], [[SHUF]] +; CHECK-NEXT: [[REVSHUF:%.*]] = shufflevector <4 x i32> [[ADD]], <4 x i32> poison, <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[REVSHUF]] +; + %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> + %add = add <4 x i32> %shuf, %shuf + %revshuf = shufflevector <4 x i32> %add, <4 x i32> poison, <4 x i32> + ret <4 x i32> %revshuf +} + +define <4 x i32> @fold_lookthrough_binop_different_operands(<4 x i32> %x, <4 x i32> %y) { +; CHECK-LABEL: @fold_lookthrough_binop_different_operands( +; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> +; CHECK-NEXT: [[ADD:%.*]] = add <4 x i32> [[SHUF]], [[Y:%.*]] +; CHECK-NEXT: [[REVSHUF:%.*]] = shufflevector <4 x i32> [[ADD]], <4 x i32> poison, <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[REVSHUF]] +; + %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> + %add = add <4 x i32> %shuf, %y + %revshuf = shufflevector <4 x i32> %add, <4 x i32> poison, <4 x i32> + ret <4 x i32> %revshuf +} + +define <4 x i32> @fold_lookthrough_binop_multiuse(<4 x i32> %x) { +; CHECK-LABEL: @fold_lookthrough_binop_multiuse( +; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> +; CHECK-NEXT: [[ADD:%.*]] = add <4 x i32> [[SHUF]], [[SHUF]] +; CHECK-NEXT: [[REVSHUF:%.*]] = shufflevector <4 x i32> [[ADD]], <4 x i32> poison, <4 x i32> +; CHECK-NEXT: [[ADD2:%.*]] = add <4 x i32> [[SHUF]], [[REVSHUF]] +; CHECK-NEXT: ret <4 x i32> [[ADD2]] +; + %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> + %add = add <4 x i32> %shuf, %shuf + %revshuf = shufflevector <4 x i32> %add, <4 x i32> poison, <4 x i32> + %add2 = add <4 x i32> %shuf, %revshuf + ret <4 x i32> %add2 +} + +define <4 x i64> @fold_lookthrough_cast_chain(<4 x i16> %x) { +; CHECK-LABEL: @fold_lookthrough_cast_chain( +; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i16> [[X:%.*]], <4 x i16> poison, <4 x i32> +; CHECK-NEXT: [[ZEXT:%.*]] = zext <4 x i16> [[SHUF]] to <4 x i32> +; CHECK-NEXT: [[SEXT:%.*]] = sext <4 x i32> [[ZEXT]] to <4 x i64> +; CHECK-NEXT: [[REVSHUF:%.*]] = shufflevector <4 x i64> [[SEXT]], <4 x i64> poison, <4 x i32> +; CHECK-NEXT: ret <4 x i64> [[REVSHUF]] +; + %shuf = shufflevector <4 x i16> %x, <4 x i16> poison, <4 x i32> + %zext = zext <4 x i16> %shuf to <4 x i32> + %sext = sext <4 x i32> %zext to <4 x i64> + %revshuf = shufflevector <4 x i64> %sext, <4 x i64> poison, <4 x i32> + ret <4 x i64> %revshuf +} + +define <4 x i32> @fold_lookthrough_binop_chain(<4 x i32> %x) { +; CHECK-LABEL: @fold_lookthrough_binop_chain( +; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> +; CHECK-NEXT: [[ADD:%.*]] = add <4 x i32> [[SHUF]], [[SHUF]] +; CHECK-NEXT: [[ADD2:%.*]] = add <4 x i32> [[ADD]], [[ADD]] +; CHECK-NEXT: [[REVSHUF:%.*]] = shufflevector <4 x i32> [[ADD2]], <4 x i32> poison, <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[REVSHUF]] +; + %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> + %add = add <4 x i32> %shuf, %shuf + %add2 = add <4 x i32> %add, %add + %revshuf = shufflevector <4 x i32> %add2, <4 x i32> poison, <4 x i32> + ret <4 x i32> %revshuf +} + +define <4 x i64> @fold_lookthrough_cast_binop_chain(<4 x i32> %x) { +; CHECK-LABEL: @fold_lookthrough_cast_binop_chain( +; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> +; CHECK-NEXT: [[ZEXT:%.*]] = zext <4 x i32> [[SHUF]] to <4 x i64> +; CHECK-NEXT: [[ADD:%.*]] = add <4 x i64> [[ZEXT]], [[ZEXT]] +; CHECK-NEXT: [[REVSHUF:%.*]] = shufflevector <4 x i64> [[ADD]], <4 x i64> poison, <4 x i32> +; CHECK-NEXT: ret <4 x i64> [[REVSHUF]] +; + %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> + %zext = zext <4 x i32> %shuf to <4 x i64> + %add = add <4 x i64> %zext, %zext + %revshuf = shufflevector <4 x i64> %add, <4 x i64> poison, <4 x i32> + ret <4 x i64> %revshuf +} + +define <4 x i64> @not_fold_cast_mismatched_types(<4 x i32> %x) { +; CHECK-LABEL: @not_fold_cast_mismatched_types( +; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <2 x i32> +; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i32> [[SHUF]] to <2 x i64> +; CHECK-NEXT: [[EXTSHUF:%.*]] = shufflevector <2 x i64> [[ZEXT]], <2 x i64> poison, <4 x i32> +; CHECK-NEXT: ret <4 x i64> [[EXTSHUF]] +; + %shuf = shufflevector <4 x i32> %x, <4 x i32> poison, <2 x i32> + %zext = zext <2 x i32> %shuf to <2 x i64> + %extshuf = shufflevector <2 x i64> %zext, <2 x i64> poison, <4 x i32> + ret <4 x i64> %extshuf +} + +define <4 x float> @not_fold_binop_mismatched_types(<4 x float> %x, <4 x float> %y) { +; CHECK-LABEL: @not_fold_binop_mismatched_types( +; CHECK-NEXT: [[SHUF_X:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> poison, <2 x i32> +; CHECK-NEXT: [[SHUF_Y:%.*]] = shufflevector <4 x float> [[Y:%.*]], <4 x float> poison, <2 x i32> +; CHECK-NEXT: [[FADD:%.*]] = fadd fast <2 x float> [[SHUF_X]], [[SHUF_Y]] +; CHECK-NEXT: [[EXTSHUF:%.*]] = shufflevector <2 x float> [[FADD]], <2 x float> poison, <4 x i32> +; CHECK-NEXT: ret <4 x float> [[EXTSHUF]] +; + %shuf.x = shufflevector <4 x float> %x, <4 x float> poison, <2 x i32> + %shuf.y = shufflevector <4 x float> %y, <4 x float> poison, <2 x i32> + %fadd = fadd fast <2 x float> %shuf.x, %shuf.y + %extshuf = shufflevector <2 x float> %fadd, <2 x float> poison, <4 x i32> + ret <4 x float> %extshuf +} -- GitLab From 605ae4e93be8976095c7eedf5c08bfdb9ff71257 Mon Sep 17 00:00:00 2001 From: Tom Eccles Date: Mon, 20 May 2024 10:58:18 +0100 Subject: [PATCH 076/793] [flang][HLFIR] Adapt SimplifyHLFIRIntrinsics to run on all top level ops (#92573) This means that this pass will also run on hlfir intrinsics which are not inside of functions. See RFC: https://discourse.llvm.org/t/rfc-add-an-interface-for-top-level-container-operations Some of the changes are from moving the declaration and definition of the constructor into tablegen (as requested during code review of another pass). --- flang/include/flang/Optimizer/HLFIR/Passes.h | 1 - flang/include/flang/Optimizer/HLFIR/Passes.td | 3 +-- flang/include/flang/Tools/CLOptions.inc | 3 ++- .../HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp | 11 +++-------- flang/test/Driver/mlir-pass-pipeline.f90 | 9 ++++++++- flang/test/Fir/basic-program.fir | 7 +++++++ 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/flang/include/flang/Optimizer/HLFIR/Passes.h b/flang/include/flang/Optimizer/HLFIR/Passes.h index 3314e0b887f6..ef47c94b67a8 100644 --- a/flang/include/flang/Optimizer/HLFIR/Passes.h +++ b/flang/include/flang/Optimizer/HLFIR/Passes.h @@ -25,7 +25,6 @@ namespace hlfir { std::unique_ptr createConvertHLFIRtoFIRPass(); std::unique_ptr createBufferizeHLFIRPass(); std::unique_ptr createLowerHLFIRIntrinsicsPass(); -std::unique_ptr createSimplifyHLFIRIntrinsicsPass(); std::unique_ptr createInlineElementalsPass(); std::unique_ptr createLowerHLFIROrderedAssignmentsPass(); std::unique_ptr createOptimizedBufferizationPass(); diff --git a/flang/include/flang/Optimizer/HLFIR/Passes.td b/flang/include/flang/Optimizer/HLFIR/Passes.td index dae96b3f767e..806d1f202975 100644 --- a/flang/include/flang/Optimizer/HLFIR/Passes.td +++ b/flang/include/flang/Optimizer/HLFIR/Passes.td @@ -46,9 +46,8 @@ def LowerHLFIROrderedAssignments : Pass<"lower-hlfir-ordered-assignments", "::ml ]; } -def SimplifyHLFIRIntrinsics : Pass<"simplify-hlfir-intrinsics", "::mlir::func::FuncOp"> { +def SimplifyHLFIRIntrinsics : Pass<"simplify-hlfir-intrinsics"> { let summary = "Simplify HLFIR intrinsic operations that don't need to result in runtime calls"; - let constructor = "hlfir::createSimplifyHLFIRIntrinsicsPass()"; } def InlineElementals : Pass<"inline-elementals", "::mlir::func::FuncOp"> { diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc index 61e591f2086d..e0ab9d5f0429 100644 --- a/flang/include/flang/Tools/CLOptions.inc +++ b/flang/include/flang/Tools/CLOptions.inc @@ -317,7 +317,8 @@ inline void createHLFIRToFIRPassPipeline( mlir::PassManager &pm, llvm::OptimizationLevel optLevel = defaultOptLevel) { if (optLevel.isOptimizingForSpeed()) { addCanonicalizerPassWithoutRegionSimplification(pm); - pm.addPass(hlfir::createSimplifyHLFIRIntrinsicsPass()); + addNestedPassToAllTopLevelOperations( + pm, hlfir::createSimplifyHLFIRIntrinsics); } pm.addPass(hlfir::createInlineElementalsPass()); if (optLevel.isOptimizingForSpeed()) { diff --git a/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp b/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp index b761563eba0f..6153c82fa734 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp @@ -94,7 +94,6 @@ class SimplifyHLFIRIntrinsics : public hlfir::impl::SimplifyHLFIRIntrinsicsBase { public: void runOnOperation() override { - mlir::func::FuncOp func = this->getOperation(); mlir::MLIRContext *context = &getContext(); mlir::RewritePatternSet patterns(context); patterns.insert(context); @@ -108,16 +107,12 @@ public: }); target.markUnknownOpDynamicallyLegal( [](mlir::Operation *) { return true; }); - if (mlir::failed( - mlir::applyFullConversion(func, target, std::move(patterns)))) { - mlir::emitError(func->getLoc(), + if (mlir::failed(mlir::applyFullConversion(getOperation(), target, + std::move(patterns)))) { + mlir::emitError(getOperation()->getLoc(), "failure in HLFIR intrinsic simplification"); signalPassFailure(); } } }; } // namespace - -std::unique_ptr hlfir::createSimplifyHLFIRIntrinsicsPass() { - return std::make_unique(); -} diff --git a/flang/test/Driver/mlir-pass-pipeline.f90 b/flang/test/Driver/mlir-pass-pipeline.f90 index 4ebac7c3fb65..7130024e43b9 100644 --- a/flang/test/Driver/mlir-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-pass-pipeline.f90 @@ -13,9 +13,16 @@ end program ! ALL: Fortran::lower::VerifierPass ! O2-NEXT: Canonicalizer -! O2-NEXT: 'func.func' Pipeline +! O2-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] +! O2-NEXT: 'fir.global' Pipeline +! O2-NEXT: SimplifyHLFIRIntrinsics +! ALL: 'func.func' Pipeline ! O2-NEXT: SimplifyHLFIRIntrinsics ! ALL: InlineElementals +! O2-NEXT: 'omp.declare_reduction' Pipeline +! O2-NEXT: SimplifyHLFIRIntrinsics +! O2-NEXT: 'omp.private' Pipeline +! O2-NEXT: SimplifyHLFIRIntrinsics ! ALL: LowerHLFIROrderedAssignments ! ALL-NEXT: LowerHLFIRIntrinsics ! ALL-NEXT: BufferizeHLFIR diff --git a/flang/test/Fir/basic-program.fir b/flang/test/Fir/basic-program.fir index 02fb84ed8c87..9e3d3c18337d 100644 --- a/flang/test/Fir/basic-program.fir +++ b/flang/test/Fir/basic-program.fir @@ -17,9 +17,16 @@ func.func @_QQmain() { // PASSES: Pass statistics report // PASSES: Canonicalizer +// PASSES-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] +// PASSES-NEXT: 'fir.global' Pipeline +// PASSES-NEXT: SimplifyHLFIRIntrinsics // PASSES-NEXT: 'func.func' Pipeline // PASSES-NEXT: SimplifyHLFIRIntrinsics // PASSES-NEXT: InlineElementals +// PASSES-NEXT: 'omp.declare_reduction' Pipeline +// PASSES-NEXT: SimplifyHLFIRIntrinsics +// PASSES-NEXT: 'omp.private' Pipeline +// PASSES-NEXT: SimplifyHLFIRIntrinsics // PASSES-NEXT: Canonicalizer // PASSES-NEXT: CSE // PASSES-NEXT: (S) 0 num-cse'd - Number of operations CSE'd -- GitLab From 1ef081b05c562936fc025dde39b444066d9d470f Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi Date: Mon, 20 May 2024 18:54:48 +0900 Subject: [PATCH 077/793] movimm-expand-ldst.mir (d3d6565c2453) requires asserts --- llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir b/llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir index 1ec2a00f6769..72529807d5d5 100644 --- a/llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir +++ b/llvm/test/CodeGen/AArch64/movimm-expand-ldst.mir @@ -1,5 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 # RUN: llc -mtriple=aarch64 -verify-machineinstrs -run-pass=aarch64-expand-pseudo -run-pass=aarch64-ldst-opt -debug-only=aarch64-ldst-opt %s -o - | FileCheck %s +# REQUIRES: asserts --- name: test_fold_repeating_constant_load tracksRegLiveness: true -- GitLab From 9f449c34278191193f2f2cbc96c333548ad20238 Mon Sep 17 00:00:00 2001 From: Han-Kuan Chen Date: Mon, 20 May 2024 18:46:30 +0800 Subject: [PATCH 078/793] [SLP] NFC. Use TreeEntry::getOperand if setOperandsInOrder is called (#92727) already. --- .../Transforms/Vectorize/SLPVectorizer.cpp | 72 +++++-------------- 1 file changed, 17 insertions(+), 55 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index d21b5e1cc041..140a1b1ffbaf 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -6916,15 +6916,8 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, std::nullopt, CurrentOrder); LLVM_DEBUG(dbgs() << "SLP: added inserts bundle.\n"); - constexpr int NumOps = 2; - ValueList VectorOperands[NumOps]; - for (int I = 0; I < NumOps; ++I) { - for (Value *V : VL) - VectorOperands[I].push_back(cast(V)->getOperand(I)); - - TE->setOperand(I, VectorOperands[I]); - } - buildTree_rec(VectorOperands[NumOps - 1], Depth + 1, {TE, NumOps - 1}); + TE->setOperandsInOrder(); + buildTree_rec(TE->getOperand(1), Depth + 1, {TE, 1}); return; } case Instruction::Load: { @@ -7024,14 +7017,8 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, LLVM_DEBUG(dbgs() << "SLP: added a vector of casts.\n"); TE->setOperandsInOrder(); - for (unsigned I : seq(0, VL0->getNumOperands())) { - ValueList Operands; - // Prepare the operand vector. - for (Value *V : VL) - Operands.push_back(cast(V)->getOperand(I)); - - buildTree_rec(Operands, Depth + 1, {TE, I}); - } + for (unsigned I : seq(0, VL0->getNumOperands())) + buildTree_rec(TE->getOperand(I), Depth + 1, {TE, I}); return; } case Instruction::ICmp: @@ -7116,14 +7103,8 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, } TE->setOperandsInOrder(); - for (unsigned I : seq(0, VL0->getNumOperands())) { - ValueList Operands; - // Prepare the operand vector. - for (Value *V : VL) - Operands.push_back(cast(V)->getOperand(I)); - - buildTree_rec(Operands, Depth + 1, {TE, I}); - } + for (unsigned I : seq(0, VL0->getNumOperands())) + buildTree_rec(TE->getOperand(I), Depth + 1, {TE, I}); return; } case Instruction::GetElementPtr: { @@ -7182,30 +7163,17 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, return; } case Instruction::Store: { - // Check if the stores are consecutive or if we need to swizzle them. - ValueList Operands(VL.size()); - auto *OIter = Operands.begin(); - for (Value *V : VL) { - auto *SI = cast(V); - *OIter = SI->getValueOperand(); - ++OIter; - } - // Check that the sorted pointer operands are consecutive. - if (CurrentOrder.empty()) { - // Original stores are consecutive and does not require reordering. - TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, - ReuseShuffleIndices); - TE->setOperandsInOrder(); - buildTree_rec(Operands, Depth + 1, {TE, 0}); - LLVM_DEBUG(dbgs() << "SLP: added a vector of stores.\n"); - } else { + bool Consecutive = CurrentOrder.empty(); + if (!Consecutive) fixupOrderingIndices(CurrentOrder); - TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, - ReuseShuffleIndices, CurrentOrder); - TE->setOperandsInOrder(); - buildTree_rec(Operands, Depth + 1, {TE, 0}); + TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, + ReuseShuffleIndices, CurrentOrder); + TE->setOperandsInOrder(); + buildTree_rec(TE->getOperand(0), Depth + 1, {TE, 0}); + if (Consecutive) + LLVM_DEBUG(dbgs() << "SLP: added a vector of stores.\n"); + else LLVM_DEBUG(dbgs() << "SLP: added a vector of jumbled stores.\n"); - } return; } case Instruction::Call: { @@ -7305,14 +7273,8 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, } TE->setOperandsInOrder(); - for (unsigned I : seq(0, VL0->getNumOperands())) { - ValueList Operands; - // Prepare the operand vector. - for (Value *V : VL) - Operands.push_back(cast(V)->getOperand(I)); - - buildTree_rec(Operands, Depth + 1, {TE, I}); - } + for (unsigned I : seq(0, VL0->getNumOperands())) + buildTree_rec(TE->getOperand(I), Depth + 1, {TE, I}); return; } default: -- GitLab From 6733a505a1afb8eb4db2f6d85426d79ff0dc5eee Mon Sep 17 00:00:00 2001 From: Sergio Afonso Date: Mon, 20 May 2024 12:13:36 +0100 Subject: [PATCH 079/793] [MLIR][OpenMP] NFC: Split OpenMP dialect definitions (#91741) This patch splits definitions for the OpenMP dialect into multiple files to simplify the addition of new features, reduce merge conflicts, make it easier to understand, etc. The split is based on the structure of the more mature LLVMIR dialect. More specifically: - The OpenMP dialect definition is located in OpenMPDialect.td. - Base classes for OpenMP operations and types, as well as generic OpenMP types are moved to OpenMPOpBase.td. - OpenMP enumeration attributes, their case attributes and shared base classes for these are placed in OpenMPEnums.td. - Other OpenMP attributes are separated into OpenMPAttrDefs.td. - OpenMPOps.td only contains operation definitions. Even though this change should be useful on its own, it is intended as a precursor to a follow-up PR in which operation arguments and attributes are split into clause-specific classes which are then shared by all operations to which they apply to. Without this prior change, that approach would make the OpenMPOps.td file harder to navigate. --- .../mlir/Dialect/OpenMP/OpenMPAttrDefs.td | 79 ++++++ .../mlir/Dialect/OpenMP/OpenMPDialect.td | 22 ++ .../mlir/Dialect/OpenMP/OpenMPEnums.td | 211 +++++++++++++++ .../mlir/Dialect/OpenMP/OpenMPOpBase.td | 48 ++++ mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td | 245 +----------------- .../Dialect/OpenMP/OpenMPOpsInterfaces.td | 6 +- 6 files changed, 371 insertions(+), 240 deletions(-) create mode 100644 mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td create mode 100644 mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.td create mode 100644 mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td create mode 100644 mlir/include/mlir/Dialect/OpenMP/OpenMPOpBase.td diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td new file mode 100644 index 000000000000..704d0b2220e8 --- /dev/null +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td @@ -0,0 +1,79 @@ +//=== OpenMPAttrDefs.td - OpenMP Attributes definition -----*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef OPENMP_ATTR_DEFS +#define OPENMP_ATTR_DEFS + +include "mlir/Dialect/OpenMP/OpenMPDialect.td" +include "mlir/Dialect/OpenMP/OpenMPEnums.td" +include "mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td" +include "mlir/Dialect/OpenMP/OpenMPTypeInterfaces.td" +include "mlir/IR/AttrTypeBase.td" +include "mlir/IR/CommonAttrConstraints.td" + +class OpenMP_Attr traits = [], + string baseCppClass = "::mlir::Attribute"> + : AttrDef { + let mnemonic = attrMnemonic; +} + +//===----------------------------------------------------------------------===// +// DeclareTargetAttr +//===----------------------------------------------------------------------===// + +def DeclareTargetAttr : OpenMP_Attr<"DeclareTarget", "declaretarget"> { + let parameters = (ins + OptionalParameter<"DeclareTargetDeviceTypeAttr">:$device_type, + OptionalParameter<"DeclareTargetCaptureClauseAttr">:$capture_clause + ); + + let assemblyFormat = "`<` struct(params) `>`"; +} + +//===----------------------------------------------------------------------===// +// FlagsAttr +//===----------------------------------------------------------------------===// + +// Runtime library flags attribute that holds information for lowering to LLVM. +def FlagsAttr : OpenMP_Attr<"Flags", "flags"> { + let parameters = (ins + DefaultValuedParameter<"uint32_t", "0">:$debug_kind, + DefaultValuedParameter<"bool", "false">:$assume_teams_oversubscription, + DefaultValuedParameter<"bool", "false">:$assume_threads_oversubscription, + DefaultValuedParameter<"bool", "false">:$assume_no_thread_state, + DefaultValuedParameter<"bool", "false">:$assume_no_nested_parallelism, + DefaultValuedParameter<"bool", "false">:$no_gpu_lib, + DefaultValuedParameter<"uint32_t", "50">:$openmp_device_version + ); + + let assemblyFormat = "`<` struct(params) `>`"; +} + +//===----------------------------------------------------------------------===// +// TaskDependArrayAttr +//===----------------------------------------------------------------------===// + +def TaskDependArrayAttr + : TypedArrayAttrBase { + let constBuilderCall = ?; +} + +//===----------------------------------------------------------------------===// +// VersionAttr +//===----------------------------------------------------------------------===// + +def VersionAttr : OpenMP_Attr<"Version", "version"> { + let parameters = (ins + "uint32_t":$version + ); + + let assemblyFormat = "`<` struct(params) `>`"; +} + +#endif // OPENMP_ATTR_DEFS diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.td new file mode 100644 index 000000000000..459cc7843580 --- /dev/null +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPDialect.td @@ -0,0 +1,22 @@ +//===- OpenMPDialect.td - OpenMP dialect definition --------*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef OPENMP_DIALECT +#define OPENMP_DIALECT + +include "mlir/IR/DialectBase.td" + +def OpenMP_Dialect : Dialect { + let name = "omp"; + let cppNamespace = "::mlir::omp"; + let dependentDialects = ["::mlir::LLVM::LLVMDialect, ::mlir::func::FuncDialect"]; + let useDefaultAttributePrinterParser = 1; + let useDefaultTypePrinterParser = 1; +} + +#endif // OPENMP_DIALECT diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td new file mode 100644 index 000000000000..bf3d33819e9a --- /dev/null +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPEnums.td @@ -0,0 +1,211 @@ +//===-- OpenMPEnums.td - OpenMP dialect enum file ----------*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef OPENMP_ENUMS +#define OPENMP_ENUMS + +include "mlir/Dialect/OpenMP/OpenMPDialect.td" +include "mlir/IR/EnumAttr.td" + +include "mlir/Dialect/OpenMP/OmpCommon.td" + +//===----------------------------------------------------------------------===// +// Base classes for OpenMP enum attributes. +//===----------------------------------------------------------------------===// + +class OpenMP_I32EnumAttr cases> + : I32EnumAttr { + let genSpecializedAttr = 0; + let cppNamespace = "::mlir::omp"; +} + +class OpenMP_BitEnumAttr cases> + : I32BitEnumAttr { + let genSpecializedAttr = 0; + let cppNamespace = "::mlir::omp"; +} + +class OpenMP_EnumAttr + : EnumAttr; + + +//===----------------------------------------------------------------------===// +// capture_clause enum. +//===----------------------------------------------------------------------===// + +def CaptureClauseTo : I32EnumAttrCase<"to", 0>; +def CaptureClauseLink : I32EnumAttrCase<"link", 1>; +def CaptureClauseEnter : I32EnumAttrCase<"enter", 2>; + +def DeclareTargetCaptureClause : OpenMP_I32EnumAttr< + "DeclareTargetCaptureClause", + "capture clause", [ + CaptureClauseTo, + CaptureClauseLink, + CaptureClauseEnter + ]>; + +def DeclareTargetCaptureClauseAttr : OpenMP_EnumAttr { + let assemblyFormat = "`(` $value `)`"; +} + +//===----------------------------------------------------------------------===// +// clause_depend enum. +//===----------------------------------------------------------------------===// + +def ClauseDependSource : I32EnumAttrCase<"dependsource", 0>; +def ClauseDependSink : I32EnumAttrCase<"dependsink", 1>; + +def ClauseDepend : OpenMP_I32EnumAttr< + "ClauseDepend", + "depend clause", [ + ClauseDependSource, + ClauseDependSink + ]>; + +def ClauseDependAttr : OpenMP_EnumAttr { + let assemblyFormat = "`(` $value `)`"; +} + +//===----------------------------------------------------------------------===// +// clause_requires enum. +//===----------------------------------------------------------------------===// + +// atomic_default_mem_order clause values not defined here because they can be +// represented by the OMPC_MemoryOrder enumeration instead. +def ClauseRequiresNone : I32BitEnumAttrCaseNone<"none">; +def ClauseRequiresReverseOffload : I32BitEnumAttrCaseBit<"reverse_offload", 0>; +def ClauseRequiresUnifiedAddress : I32BitEnumAttrCaseBit<"unified_address", 1>; +def ClauseRequiresUnifiedSharedMemory + : I32BitEnumAttrCaseBit<"unified_shared_memory", 2>; +def ClauseRequiresDynamicAllocators + : I32BitEnumAttrCaseBit<"dynamic_allocators", 3>; + +def ClauseRequires : OpenMP_BitEnumAttr< + "ClauseRequires", + "requires clauses", [ + ClauseRequiresNone, + ClauseRequiresReverseOffload, + ClauseRequiresUnifiedAddress, + ClauseRequiresUnifiedSharedMemory, + ClauseRequiresDynamicAllocators + ]>; + +def ClauseRequiresAttr : OpenMP_EnumAttr; + +//===----------------------------------------------------------------------===// +// clause_task_depend enum. +//===----------------------------------------------------------------------===// + +def ClauseTaskDependIn : I32EnumAttrCase<"taskdependin", 0>; +def ClauseTaskDependOut : I32EnumAttrCase<"taskdependout", 1>; +def ClauseTaskDependInOut : I32EnumAttrCase<"taskdependinout", 2>; + +def ClauseTaskDepend : OpenMP_I32EnumAttr< + "ClauseTaskDepend", + "depend clause in a target or task construct", [ + ClauseTaskDependIn, + ClauseTaskDependOut, + ClauseTaskDependInOut + ]>; + +def ClauseTaskDependAttr : OpenMP_EnumAttr { + let assemblyFormat = "`(` $value `)`"; +} + +//===----------------------------------------------------------------------===// +// data_sharing_type enum. +//===----------------------------------------------------------------------===// + +def DataSharingTypePrivate : I32EnumAttrCase<"Private", 0, "private">; +def DataSharingTypeFirstPrivate + : I32EnumAttrCase<"FirstPrivate", 1, "firstprivate">; + +def DataSharingClauseType : OpenMP_I32EnumAttr< + "DataSharingClauseType", + "Type of a data-sharing clause", [ + DataSharingTypePrivate, + DataSharingTypeFirstPrivate + ]>; + +def DataSharingClauseTypeAttr : OpenMP_EnumAttr { + let assemblyFormat = "`{` `type` `=` $value `}`"; +} + +//===----------------------------------------------------------------------===// +// device_type enum. +//===----------------------------------------------------------------------===// + +def DeviceTypeAny : I32EnumAttrCase<"any", 0>; +def DeviceTypeHost : I32EnumAttrCase<"host", 1>; +def DeviceTypeNoHost : I32EnumAttrCase<"nohost", 2>; + +def DeclareTargetDeviceType : OpenMP_I32EnumAttr< + "DeclareTargetDeviceType", + "device_type clause", [ + DeviceTypeAny, + DeviceTypeHost, + DeviceTypeNoHost + ]>; + +def DeclareTargetDeviceTypeAttr : OpenMP_EnumAttr { + let assemblyFormat = "`(` $value `)`"; +} + +//===----------------------------------------------------------------------===// +// sched_mod enum. +//===----------------------------------------------------------------------===// + +def OpenMP_ScheduleModNone : I32EnumAttrCase<"none", 0>; +def OpenMP_ScheduleModMonotonic : I32EnumAttrCase<"monotonic", 1>; +def OpenMP_ScheduleModNonmonotonic : I32EnumAttrCase<"nonmonotonic", 2>; +// FIXME: remove this value for the modifier because this is handled using a +// separate attribute +def OpenMP_ScheduleModSimd : I32EnumAttrCase<"simd", 3>; + +def ScheduleModifier : OpenMP_I32EnumAttr< + "ScheduleModifier", + "OpenMP Schedule Modifier", [ + OpenMP_ScheduleModNone, + OpenMP_ScheduleModMonotonic, + OpenMP_ScheduleModNonmonotonic, + OpenMP_ScheduleModSimd + ]>; + +def ScheduleModifierAttr : OpenMP_EnumAttr; + +//===----------------------------------------------------------------------===// +// variable_capture_kind enum. +//===----------------------------------------------------------------------===// + +def CaptureThis : I32EnumAttrCase<"This", 0>; +def CaptureByRef : I32EnumAttrCase<"ByRef", 1>; +def CaptureByCopy : I32EnumAttrCase<"ByCopy", 2>; +def CaptureVLAType : I32EnumAttrCase<"VLAType", 3>; + +def VariableCaptureKind : OpenMP_I32EnumAttr< + "VariableCaptureKind", + "variable capture kind", [ + CaptureThis, + CaptureByRef, + CaptureByCopy, + CaptureVLAType + ]>; + +def VariableCaptureKindAttr : OpenMP_EnumAttr { + let assemblyFormat = "`(` $value `)`"; +} + +#endif // OPENMP_ENUMS diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpBase.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpBase.td new file mode 100644 index 000000000000..b98d87aa74a6 --- /dev/null +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpBase.td @@ -0,0 +1,48 @@ +//===- OpenMPOpBase.td - OpenMP dialect shared definitions -*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains shared definitions for the OpenMP dialect. +// +//===----------------------------------------------------------------------===// + +#ifndef OPENMP_OP_BASE +#define OPENMP_OP_BASE + +include "mlir/Dialect/OpenMP/OpenMPAttrDefs.td" +include "mlir/Dialect/OpenMP/OpenMPDialect.td" +include "mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td" +include "mlir/Dialect/OpenMP/OpenMPTypeInterfaces.td" +include "mlir/IR/OpBase.td" + +//===----------------------------------------------------------------------===// +// OpenMP dialect type constraints. +//===----------------------------------------------------------------------===// + +class OpenMP_Type : + TypeDef { + let mnemonic = typeMnemonic; +} + +// Type which can be constraint accepting standard integers and indices. +def IntLikeType : AnyTypeOf<[AnyInteger, Index]>; + +def OpenMP_PointerLikeType : TypeAlias; + +def OpenMP_MapBoundsType : OpenMP_Type<"MapBounds", "map_bounds_ty"> { + let summary = "Type for representing omp map clause bounds information"; +} + +//===----------------------------------------------------------------------===// +// Base classes for OpenMP dialect operations. +//===----------------------------------------------------------------------===// + +class OpenMP_Op traits = []> : + Op; + +#endif // OPENMP_OP_BASE diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td index 29c287cad06e..122abbe7cc97 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -14,145 +14,20 @@ #ifndef OPENMP_OPS #define OPENMP_OPS +include "mlir/Dialect/LLVMIR/LLVMOpBase.td" +include "mlir/Dialect/OpenACCMPCommon/Interfaces/AtomicInterfaces.td" +include "mlir/Dialect/OpenMP/OpenMPAttrDefs.td" +include "mlir/Dialect/OpenMP/OpenMPOpBase.td" +include "mlir/Interfaces/ControlFlowInterfaces.td" +include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/EnumAttr.td" include "mlir/IR/OpBase.td" -include "mlir/Interfaces/SideEffectInterfaces.td" -include "mlir/Interfaces/ControlFlowInterfaces.td" include "mlir/IR/SymbolInterfaces.td" -include "mlir/Dialect/LLVMIR/LLVMOpBase.td" -include "mlir/Dialect/OpenACCMPCommon/Interfaces/AtomicInterfaces.td" -include "mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td" -include "mlir/Dialect/OpenMP/OpenMPTypeInterfaces.td" - -def OpenMP_Dialect : Dialect { - let name = "omp"; - let cppNamespace = "::mlir::omp"; - let dependentDialects = ["::mlir::LLVM::LLVMDialect, ::mlir::func::FuncDialect"]; - let useDefaultAttributePrinterParser = 1; - let useDefaultTypePrinterParser = 1; -} - -// OmpCommon requires definition of OpenACC_Dialect. -include "mlir/Dialect/OpenMP/OmpCommon.td" - -//===----------------------------------------------------------------------===// -// OpenMP Attributes -//===----------------------------------------------------------------------===// - -class OpenMP_Attr traits = [], - string baseCppClass = "::mlir::Attribute"> - : AttrDef { - let mnemonic = attrMnemonic; -} - -def VersionAttr : OpenMP_Attr<"Version", "version"> { - let parameters = (ins - "uint32_t":$version - ); - - let assemblyFormat = "`<` struct(params) `>`"; -} - -//===----------------------------------------------------------------------===// -// Runtime library flag's attribute that holds information for lowering to LLVM -//===----------------------------------------------------------------------===// - -def FlagsAttr : OpenMP_Attr<"Flags", "flags"> { - let parameters = (ins - DefaultValuedParameter<"uint32_t", "0">:$debug_kind, - DefaultValuedParameter<"bool", "false">:$assume_teams_oversubscription, - DefaultValuedParameter<"bool", "false">:$assume_threads_oversubscription, - DefaultValuedParameter<"bool", "false">:$assume_no_thread_state, - DefaultValuedParameter<"bool", "false">:$assume_no_nested_parallelism, - DefaultValuedParameter<"bool", "false">:$no_gpu_lib, - DefaultValuedParameter<"uint32_t", "50">:$openmp_device_version - ); - - let assemblyFormat = "`<` struct(params) `>`"; -} - - -class OpenMP_Op traits = []> : - Op; - -// Type which can be constraint accepting standard integers and indices. -def IntLikeType : AnyTypeOf<[AnyInteger, Index]>; - -def OpenMP_PointerLikeType : TypeAlias; - -class OpenMP_Type : TypeDef { - let mnemonic = typeMnemonic; -} - -//===----------------------------------------------------------------------===// -// 2.12.7 Declare Target Directive -//===----------------------------------------------------------------------===// - -def DeviceTypeAny : I32EnumAttrCase<"any", 0>; -def DeviceTypeHost : I32EnumAttrCase<"host", 1>; -def DeviceTypeNoHost : I32EnumAttrCase<"nohost", 2>; - -def DeclareTargetDeviceType : I32EnumAttr< - "DeclareTargetDeviceType", - "device_type clause", - [DeviceTypeAny, DeviceTypeHost, DeviceTypeNoHost]> { - let genSpecializedAttr = 0; - let cppNamespace = "::mlir::omp"; -} - -def DeclareTargetDeviceTypeAttr : EnumAttr { - let assemblyFormat = "`(` $value `)`"; -} - -def CaptureClauseTo : I32EnumAttrCase<"to", 0>; -def CaptureClauseLink : I32EnumAttrCase<"link", 1>; -def CaptureClauseEnter : I32EnumAttrCase<"enter", 2>; - -def DeclareTargetCaptureClause : I32EnumAttr< - "DeclareTargetCaptureClause", - "capture clause", - [CaptureClauseTo, CaptureClauseLink, CaptureClauseEnter]> { - let genSpecializedAttr = 0; - let cppNamespace = "::mlir::omp"; -} - -def DeclareTargetCaptureClauseAttr : EnumAttr { - let assemblyFormat = "`(` $value `)`"; -} - -def DeclareTargetAttr : OpenMP_Attr<"DeclareTarget", "declaretarget"> { - let parameters = (ins - OptionalParameter<"DeclareTargetDeviceTypeAttr">:$device_type, - OptionalParameter<"DeclareTargetCaptureClauseAttr">:$capture_clause - ); - - let assemblyFormat = "`<` struct(params) `>`"; -} //===----------------------------------------------------------------------===// // 2.19.4 Data-Sharing Attribute Clauses //===----------------------------------------------------------------------===// -def DataSharingTypePrivate : I32EnumAttrCase<"Private", 0, "private">; -def DataSharingTypeFirstPrivate : I32EnumAttrCase<"FirstPrivate", 1, "firstprivate">; - -def DataSharingClauseType : I32EnumAttr< - "DataSharingClauseType", - "Type of a data-sharing clause", - [DataSharingTypePrivate, DataSharingTypeFirstPrivate]> { - let genSpecializedAttr = 0; - let cppNamespace = "::mlir::omp"; -} - -def DataSharingClauseTypeAttr : EnumAttr< - OpenMP_Dialect, DataSharingClauseType, "data_sharing_type"> { - let assemblyFormat = "`{` `type` `=` $value `}`"; -} - def PrivateClauseOp : OpenMP_Op<"private", [IsolatedFromAbove]> { let summary = "Provides declaration of [first]private logic."; let description = [{ @@ -403,23 +278,6 @@ def TeamsOp : OpenMP_Op<"teams", [ let hasVerifier = 1; } -def OMP_ScheduleModNone : I32EnumAttrCase<"none", 0>; -def OMP_ScheduleModMonotonic : I32EnumAttrCase<"monotonic", 1>; -def OMP_ScheduleModNonmonotonic : I32EnumAttrCase<"nonmonotonic", 2>; -// FIXME: remove this value for the modifier because this is handled using a -// separate attribute -def OMP_ScheduleModSIMD : I32EnumAttrCase<"simd", 3>; - -def ScheduleModifier - : I32EnumAttr<"ScheduleModifier", "OpenMP Schedule Modifier", - [OMP_ScheduleModNone, OMP_ScheduleModMonotonic, - OMP_ScheduleModNonmonotonic, OMP_ScheduleModSIMD]> { - let genSpecializedAttr = 0; - let cppNamespace = "::mlir::omp"; -} -def ScheduleModifierAttr : EnumAttr; - //===----------------------------------------------------------------------===// // 2.8.1 Sections Construct //===----------------------------------------------------------------------===// @@ -904,26 +762,6 @@ def DistributeOp : OpenMP_Op<"distribute", [AttrSizedOperandSegments, // 2.10.1 task Construct //===----------------------------------------------------------------------===// -def ClauseTaskDependIn : I32EnumAttrCase<"taskdependin", 0>; -def ClauseTaskDependOut : I32EnumAttrCase<"taskdependout", 1>; -def ClauseTaskDependInOut : I32EnumAttrCase<"taskdependinout", 2>; - -def ClauseTaskDepend : I32EnumAttr< - "ClauseTaskDepend", - "depend clause in a target or task construct", - [ClauseTaskDependIn, ClauseTaskDependOut, ClauseTaskDependInOut]> { - let genSpecializedAttr = 0; - let cppNamespace = "::mlir::omp"; -} -def ClauseTaskDependAttr : - EnumAttr { - let assemblyFormat = "`(` $value `)`"; -} -def TaskDependArrayAttr : - TypedArrayAttrBase { - let constBuilderCall = ?; - } - def TaskOp : OpenMP_Op<"task", [AttrSizedOperandSegments, OutlineableOpenMPOpInterface, AutomaticAllocationScope, ReductionClauseInterface]> { @@ -1283,28 +1121,6 @@ def FlushOp : OpenMP_Op<"flush"> { // Map related constructs //===----------------------------------------------------------------------===// -def CaptureThis : I32EnumAttrCase<"This", 0>; -def CaptureByRef : I32EnumAttrCase<"ByRef", 1>; -def CaptureByCopy : I32EnumAttrCase<"ByCopy", 2>; -def CaptureVLAType : I32EnumAttrCase<"VLAType", 3>; - -def VariableCaptureKind : I32EnumAttr< - "VariableCaptureKind", - "variable capture kind", - [CaptureThis, CaptureByRef, CaptureByCopy, CaptureVLAType]> { - let genSpecializedAttr = 0; - let cppNamespace = "::mlir::omp"; -} - -def VariableCaptureKindAttr : EnumAttr { - let assemblyFormat = "`(` $value `)`"; -} - -def MapBoundsType : OpenMP_Type<"MapBounds", "map_bounds_ty"> { - let summary = "Type for representing omp map clause bounds information"; -} - def MapBoundsOp : OpenMP_Op<"map.bounds", [AttrSizedOperandSegments, NoMemoryEffect]> { let summary = "Represents normalized bounds information for map clauses."; @@ -1386,7 +1202,7 @@ def MapBoundsOp : OpenMP_Op<"map.bounds", Optional:$stride, DefaultValuedAttr:$stride_in_bytes, Optional:$start_idx); - let results = (outs MapBoundsType:$result); + let results = (outs OpenMP_MapBoundsType:$result); let assemblyFormat = [{ oilist( @@ -1419,7 +1235,7 @@ def MapInfoOp : OpenMP_Op<"map.info", [AttrSizedOperandSegments]> { Optional:$var_ptr_ptr, Variadic:$members, OptionalAttr:$members_index, - Variadic:$bounds, /* rank-0 to rank-{n-1} */ + Variadic:$bounds, /* rank-0 to rank-{n-1} */ OptionalAttr:$map_type, OptionalAttr:$map_capture_type, OptionalAttr:$name, @@ -1894,20 +1710,6 @@ def BarrierOp : OpenMP_Op<"barrier"> { // [5.1] 2.19.9 ordered Construct //===----------------------------------------------------------------------===// -def ClauseDependSource : I32EnumAttrCase<"dependsource", 0>; -def ClauseDependSink : I32EnumAttrCase<"dependsink", 1>; - -def ClauseDepend : I32EnumAttr< - "ClauseDepend", - "depend clause", - [ClauseDependSource, ClauseDependSink]> { - let genSpecializedAttr = 0; - let cppNamespace = "::mlir::omp"; -} -def ClauseDependAttr : EnumAttr { - let assemblyFormat = "`(` $value `)`"; -} - def OrderedOp : OpenMP_Op<"ordered"> { let summary = "ordered construct without region"; let description = [{ @@ -2377,35 +2179,4 @@ def ReductionOp : OpenMP_Op<"reduction"> { let hasVerifier = 1; } -//===----------------------------------------------------------------------===// -// 8.2 requires directive -//===----------------------------------------------------------------------===// - -// atomic_default_mem_order clause values not defined here because they can be -// represented by the OMPC_MemoryOrder enumeration instead. -def ClauseRequiresNone : I32BitEnumAttrCaseNone<"none">; -def ClauseRequiresReverseOffload : I32BitEnumAttrCaseBit<"reverse_offload", 0>; -def ClauseRequiresUnifiedAddress : I32BitEnumAttrCaseBit<"unified_address", 1>; -def ClauseRequiresUnifiedSharedMemory - : I32BitEnumAttrCaseBit<"unified_shared_memory", 2>; -def ClauseRequiresDynamicAllocators - : I32BitEnumAttrCaseBit<"dynamic_allocators", 3>; - -def ClauseRequires : I32BitEnumAttr< - "ClauseRequires", - "requires clauses", - [ - ClauseRequiresNone, - ClauseRequiresReverseOffload, - ClauseRequiresUnifiedAddress, - ClauseRequiresUnifiedSharedMemory, - ClauseRequiresDynamicAllocators - ]> { - let genSpecializedAttr = 0; - let cppNamespace = "::mlir::omp"; -} -def ClauseRequiresAttr : - EnumAttr { -} - #endif // OPENMP_OPS diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td index d9569d9d294d..31a306072d0e 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td @@ -10,8 +10,8 @@ // //===----------------------------------------------------------------------===// -#ifndef OpenMP_OPS_INTERFACES -#define OpenMP_OPS_INTERFACES +#ifndef OPENMP_OPS_INTERFACES +#define OPENMP_OPS_INTERFACES include "mlir/IR/OpBase.td" @@ -349,4 +349,4 @@ def OffloadModuleInterface : OpInterface<"OffloadModuleInterface"> { ]; } -#endif // OpenMP_OPS_INTERFACES +#endif // OPENMP_OPS_INTERFACES -- GitLab From f6ae8e6381a02b10091589d7742fab389f847ea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Degioanni?= Date: Mon, 20 May 2024 12:52:07 +0100 Subject: [PATCH 080/793] [mlir][irdl] Fix missing verifier in irdl.parametric (#92700) The parametric op was not checking the symbol it points to is a type or attribute. This PR also fixes a small bug where an invalid IRDL file would not end processing in mlir-opt. I also improved the error messages for the already handled irdl.base invalid symbols. --- mlir/include/mlir/Dialect/IRDL/IR/IRDLOps.td | 3 +- mlir/lib/Dialect/IRDL/IR/IRDL.cpp | 31 +++++++++++++++----- mlir/lib/Tools/mlir-opt/MlirOptMain.cpp | 2 ++ mlir/test/Dialect/IRDL/invalid.irdl.mlir | 17 ++++++++++- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/mlir/include/mlir/Dialect/IRDL/IR/IRDLOps.td b/mlir/include/mlir/Dialect/IRDL/IR/IRDLOps.td index aa6a8e93c028..d2765dec420a 100644 --- a/mlir/include/mlir/Dialect/IRDL/IR/IRDLOps.td +++ b/mlir/include/mlir/Dialect/IRDL/IR/IRDLOps.td @@ -503,7 +503,8 @@ def IRDL_BaseOp : IRDL_ConstraintOp<"base", } def IRDL_ParametricOp : IRDL_ConstraintOp<"parametric", - [ParentOneOf<["TypeOp", "AttributeOp", "OperationOp"]>, Pure]> { + [ParentOneOf<["TypeOp", "AttributeOp", "OperationOp"]>, + DeclareOpInterfaceMethods, Pure]> { let summary = "Constraints an attribute/type base and its parameters"; let description = [{ `irdl.parametric` defines a constraint that accepts only a single type diff --git a/mlir/lib/Dialect/IRDL/IR/IRDL.cpp b/mlir/lib/Dialect/IRDL/IR/IRDL.cpp index 4eae2b03024c..e4728f55b49d 100644 --- a/mlir/lib/Dialect/IRDL/IR/IRDL.cpp +++ b/mlir/lib/Dialect/IRDL/IR/IRDL.cpp @@ -132,22 +132,37 @@ LogicalResult BaseOp::verify() { return success(); } +static LogicalResult +checkSymbolIsTypeOrAttribute(SymbolTableCollection &symbolTable, + Operation *source, SymbolRefAttr symbol) { + Operation *targetOp = symbolTable.lookupNearestSymbolFrom(source, symbol); + if (!targetOp) + return source->emitOpError() << "symbol '" << symbol << "' not found"; + + if (!isa(targetOp)) + return source->emitOpError() << "symbol '" << symbol + << "' does not refer to a type or attribute " + "definition (refers to '" + << targetOp->getName() << "')"; + + return success(); +} + LogicalResult BaseOp::verifySymbolUses(SymbolTableCollection &symbolTable) { std::optional baseRef = getBaseRef(); if (!baseRef) return success(); - TypeOp typeOp = symbolTable.lookupNearestSymbolFrom(*this, *baseRef); - if (typeOp) - return success(); + return checkSymbolIsTypeOrAttribute(symbolTable, *this, *baseRef); +} - AttributeOp attrOp = - symbolTable.lookupNearestSymbolFrom(*this, *baseRef); - if (attrOp) +LogicalResult +ParametricOp::verifySymbolUses(SymbolTableCollection &symbolTable) { + std::optional baseRef = getBaseType(); + if (!baseRef) return success(); - return emitOpError() << "'" << *baseRef - << "' does not refer to a type or attribute definition"; + return checkSymbolIsTypeOrAttribute(symbolTable, *this, *baseRef); } /// Parse a value with its variadicity first. By default, the variadicity is diff --git a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp index 44c5e9826f3b..a1b2893a973b 100644 --- a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp +++ b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp @@ -266,6 +266,8 @@ LogicalResult loadIRDLDialects(StringRef irdlFile, MLIRContext &ctx) { // Parse the input file. OwningOpRef module(parseSourceFile(sourceMgr, &ctx)); + if (!module) + return failure(); // Load IRDL dialects. return irdl::loadDialects(module.get()); diff --git a/mlir/test/Dialect/IRDL/invalid.irdl.mlir b/mlir/test/Dialect/IRDL/invalid.irdl.mlir index d62bb498a7ad..f207d31cf158 100644 --- a/mlir/test/Dialect/IRDL/invalid.irdl.mlir +++ b/mlir/test/Dialect/IRDL/invalid.irdl.mlir @@ -6,7 +6,7 @@ func.func private @foo() irdl.dialect @testd { irdl.type @type { - // expected-error@+1 {{'@foo' does not refer to a type or attribute definition}} + // expected-error@+1 {{symbol '@foo' not found}} %0 = irdl.base @foo irdl.parameters(%0) } @@ -41,3 +41,18 @@ irdl.dialect @testd { irdl.parameters(%0) } } + +// ----- + +irdl.dialect @invalid_parametric { + irdl.operation @foo { + // expected-error@+1 {{symbol '@not_a_type_or_attr' does not refer to a type or attribute definition}} + %param = irdl.parametric @not_a_type_or_attr<> + irdl.results(%param) + } + + irdl.operation @not_a_type_or_attr { + %param = irdl.is i1 + irdl.results(%param) + } +} -- GitLab From 82c5d350d200ccc5365d40eac187b9ec967af727 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Mon, 20 May 2024 13:03:48 +0100 Subject: [PATCH 081/793] [VPlan] Add commutative binary OR matcher, use in transform. (#92539) Split off from https://github.com/llvm/llvm-project/pull/89386, this extends the binary matcher to support matching commuative operations. This is used for a new m_c_BinaryOr matcher, used in simplifyRecipe. PR: https://github.com/llvm/llvm-project/pull/92539 --- .../Transforms/Vectorize/VPlanPatternMatch.h | 43 +++++++++++++------ .../Transforms/Vectorize/VPlanTransforms.cpp | 4 +- .../LoopVectorize/AArch64/masked-call.ll | 9 ++-- .../LoopVectorize/AArch64/sve-tail-folding.ll | 3 +- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h index 56cbaa420129..058746880743 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h +++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h @@ -157,7 +157,7 @@ using AllUnaryRecipe_match = UnaryRecipe_match; -template struct BinaryRecipe_match { Op0_t Op0; @@ -179,18 +179,23 @@ struct BinaryRecipe_match { return false; assert(R->getNumOperands() == 2 && "recipe with matched opcode does not have 2 operands"); - return Op0.match(R->getOperand(0)) && Op1.match(R->getOperand(1)); + if (Op0.match(R->getOperand(0)) && Op1.match(R->getOperand(1))) + return true; + return Commutative && Op0.match(R->getOperand(1)) && + Op1.match(R->getOperand(0)); } }; template using BinaryVPInstruction_match = - BinaryRecipe_match; + BinaryRecipe_match; -template +template using AllBinaryRecipe_match = - BinaryRecipe_match; + BinaryRecipe_match; template inline UnaryVPInstruction_match @@ -256,10 +261,11 @@ m_ZExtOrSExt(const Op0_t &Op0) { return m_CombineOr(m_ZExt(Op0), m_SExt(Op0)); } -template -inline AllBinaryRecipe_match m_Binary(const Op0_t &Op0, - const Op1_t &Op1) { - return AllBinaryRecipe_match(Op0, Op1); +template +inline AllBinaryRecipe_match +m_Binary(const Op0_t &Op0, const Op1_t &Op1) { + return AllBinaryRecipe_match(Op0, Op1); } template @@ -268,10 +274,21 @@ m_Mul(const Op0_t &Op0, const Op1_t &Op1) { return m_Binary(Op0, Op1); } -template -inline AllBinaryRecipe_match +/// Match a binary OR operation. Note that while conceptually the operands can +/// be matched commutatively, \p Commutative defaults to false in line with the +/// IR-based pattern matching infrastructure. Use m_c_BinaryOr for a commutative +/// version of the matcher. +template +inline AllBinaryRecipe_match m_BinaryOr(const Op0_t &Op0, const Op1_t &Op1) { - return m_Binary(Op0, Op1); + return m_Binary(Op0, Op1); +} + +template +inline AllBinaryRecipe_match +m_c_BinaryOr(const Op0_t &Op0, const Op1_t &Op1) { + return m_BinaryOr(Op0, Op1); } template diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp index 4c968c2834b1..7ff8d8e0ea15 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp @@ -941,8 +941,8 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) { // recipes to be visited during simplification. VPValue *X, *Y, *X1, *Y1; if (match(&R, - m_BinaryOr(m_LogicalAnd(m_VPValue(X), m_VPValue(Y)), - m_LogicalAnd(m_VPValue(X1), m_Not(m_VPValue(Y1))))) && + m_c_BinaryOr(m_LogicalAnd(m_VPValue(X), m_VPValue(Y)), + m_LogicalAnd(m_VPValue(X1), m_Not(m_VPValue(Y1))))) && X == X1 && Y == Y1) { R.getVPSingleValue()->replaceAllUsesWith(X); return; diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/masked-call.ll b/llvm/test/Transforms/LoopVectorize/AArch64/masked-call.ll index d335ac4b6970..200c2adcf0e6 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/masked-call.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/masked-call.ll @@ -402,10 +402,9 @@ define void @test_widen_if_then_else(ptr noalias %a, ptr readnone %b) #4 { ; TFCOMMON-NEXT: [[TMP11:%.*]] = call @foo_vector( zeroinitializer, [[TMP10]]) ; TFCOMMON-NEXT: [[TMP12:%.*]] = select [[ACTIVE_LANE_MASK]], [[TMP8]], zeroinitializer ; TFCOMMON-NEXT: [[TMP13:%.*]] = call @foo_vector( [[WIDE_MASKED_LOAD]], [[TMP12]]) -; TFCOMMON-NEXT: [[TMP14:%.*]] = or [[TMP10]], [[TMP12]] ; TFCOMMON-NEXT: [[PREDPHI:%.*]] = select [[TMP10]], [[TMP11]], [[TMP13]] ; TFCOMMON-NEXT: [[TMP15:%.*]] = getelementptr inbounds i64, ptr [[B:%.*]], i64 [[INDEX]] -; TFCOMMON-NEXT: call void @llvm.masked.store.nxv2i64.p0( [[PREDPHI]], ptr [[TMP15]], i32 8, [[TMP14]]) +; TFCOMMON-NEXT: call void @llvm.masked.store.nxv2i64.p0( [[PREDPHI]], ptr [[TMP15]], i32 8, [[ACTIVE_LANE_MASK]]) ; TFCOMMON-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], [[TMP6]] ; TFCOMMON-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call @llvm.get.active.lane.mask.nxv2i1.i64(i64 [[INDEX_NEXT]], i64 1025) ; TFCOMMON-NEXT: [[TMP16:%.*]] = xor [[ACTIVE_LANE_MASK_NEXT]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer) @@ -453,16 +452,14 @@ define void @test_widen_if_then_else(ptr noalias %a, ptr readnone %b) #4 { ; TFA_INTERLEAVE-NEXT: [[TMP22:%.*]] = select [[ACTIVE_LANE_MASK2]], [[TMP14]], zeroinitializer ; TFA_INTERLEAVE-NEXT: [[TMP23:%.*]] = call @foo_vector( [[WIDE_MASKED_LOAD]], [[TMP21]]) ; TFA_INTERLEAVE-NEXT: [[TMP24:%.*]] = call @foo_vector( [[WIDE_MASKED_LOAD3]], [[TMP22]]) -; TFA_INTERLEAVE-NEXT: [[TMP25:%.*]] = or [[TMP17]], [[TMP21]] -; TFA_INTERLEAVE-NEXT: [[TMP26:%.*]] = or [[TMP18]], [[TMP22]] ; TFA_INTERLEAVE-NEXT: [[PREDPHI:%.*]] = select [[TMP17]], [[TMP19]], [[TMP23]] ; TFA_INTERLEAVE-NEXT: [[PREDPHI4:%.*]] = select [[TMP18]], [[TMP20]], [[TMP24]] ; TFA_INTERLEAVE-NEXT: [[TMP27:%.*]] = getelementptr inbounds i64, ptr [[B:%.*]], i64 [[INDEX]] ; TFA_INTERLEAVE-NEXT: [[TMP28:%.*]] = call i64 @llvm.vscale.i64() ; TFA_INTERLEAVE-NEXT: [[TMP29:%.*]] = mul i64 [[TMP28]], 2 ; TFA_INTERLEAVE-NEXT: [[TMP30:%.*]] = getelementptr inbounds i64, ptr [[TMP27]], i64 [[TMP29]] -; TFA_INTERLEAVE-NEXT: call void @llvm.masked.store.nxv2i64.p0( [[PREDPHI]], ptr [[TMP27]], i32 8, [[TMP25]]) -; TFA_INTERLEAVE-NEXT: call void @llvm.masked.store.nxv2i64.p0( [[PREDPHI4]], ptr [[TMP30]], i32 8, [[TMP26]]) +; TFA_INTERLEAVE-NEXT: call void @llvm.masked.store.nxv2i64.p0( [[PREDPHI]], ptr [[TMP27]], i32 8, [[ACTIVE_LANE_MASK]]) +; TFA_INTERLEAVE-NEXT: call void @llvm.masked.store.nxv2i64.p0( [[PREDPHI4]], ptr [[TMP30]], i32 8, [[ACTIVE_LANE_MASK2]]) ; TFA_INTERLEAVE-NEXT: [[INDEX_NEXT:%.*]] = add i64 [[INDEX]], [[TMP6]] ; TFA_INTERLEAVE-NEXT: [[TMP31:%.*]] = call i64 @llvm.vscale.i64() ; TFA_INTERLEAVE-NEXT: [[TMP32:%.*]] = mul i64 [[TMP31]], 2 diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/sve-tail-folding.ll b/llvm/test/Transforms/LoopVectorize/AArch64/sve-tail-folding.ll index 2b2742ca7ccb..63ad98b2d8ab 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/sve-tail-folding.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/sve-tail-folding.ll @@ -480,11 +480,10 @@ define void @cond_uniform_load(ptr noalias %dst, ptr noalias readonly %src, ptr ; CHECK-NEXT: [[TMP15:%.*]] = select [[ACTIVE_LANE_MASK]], [[TMP14]], zeroinitializer ; CHECK-NEXT: [[WIDE_MASKED_GATHER:%.*]] = call @llvm.masked.gather.nxv4i32.nxv4p0( [[BROADCAST_SPLAT]], i32 4, [[TMP15]], poison) ; CHECK-NEXT: [[TMP16:%.*]] = select [[ACTIVE_LANE_MASK]], [[TMP13]], zeroinitializer -; CHECK-NEXT: [[TMP18:%.*]] = or [[TMP15]], [[TMP16]] ; CHECK-NEXT: [[PREDPHI:%.*]] = select [[TMP16]], zeroinitializer, [[WIDE_MASKED_GATHER]] ; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i64 [[TMP10]] ; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds i32, ptr [[TMP17]], i32 0 -; CHECK-NEXT: call void @llvm.masked.store.nxv4i32.p0( [[PREDPHI]], ptr [[TMP19]], i32 4, [[TMP18]]) +; CHECK-NEXT: call void @llvm.masked.store.nxv4i32.p0( [[PREDPHI]], ptr [[TMP19]], i32 4, [[ACTIVE_LANE_MASK]]) ; CHECK-NEXT: [[INDEX_NEXT2]] = add i64 [[INDEX1]], [[TMP21]] ; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[INDEX1]], i64 [[TMP9]]) ; CHECK-NEXT: [[TMP22:%.*]] = xor [[ACTIVE_LANE_MASK_NEXT]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer) -- GitLab From 36899d693d91719e7e6cd0f0ee4cf579111b8509 Mon Sep 17 00:00:00 2001 From: Danila Malyutin Date: Mon, 20 May 2024 17:51:32 +0400 Subject: [PATCH 082/793] [CloneFunction] Remove check that is no longer necessary (#92577) We do not need to concern ourselves with CGSCC since all remaining CG related updates went away in fa6ea7a419f37befbed04368bcb8af4c718facbb as pointed out by @nikic in https://github.com/llvm/llvm-project/pull/87963#issuecomment-2113937182. --- llvm/lib/Transforms/Utils/CloneFunction.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp index 981183682b8b..1fef8bc46121 100644 --- a/llvm/lib/Transforms/Utils/CloneFunction.cpp +++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp @@ -825,13 +825,6 @@ void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc, if (!NewI) continue; - // Skip over non-intrinsic callsites, we don't want to remove any nodes - // from the CGSCC. - CallBase *CB = dyn_cast(NewI); - if (CB && CB->getCalledFunction() && - !CB->getCalledFunction()->isIntrinsic()) - continue; - if (Value *V = simplifyInstruction(NewI, DL)) { NewI->replaceAllUsesWith(V); -- GitLab From 04ae6e600a3090ccc1f80d0110a1108aa73a54f8 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Mon, 20 May 2024 21:52:38 +0800 Subject: [PATCH 083/793] [ValueTracking] Fix incorrect inferrence about the signbit of sqrt (#92510) According to IEEE Std 754-2019, `sqrt` returns nan when the input is negative (except for -0). In this case, we cannot make assumptions about sign bit of the result. Fixes https://github.com/llvm/llvm-project/issues/92217 --- llvm/lib/Analysis/ValueTracking.cpp | 5 +-- .../test/Transforms/InstCombine/known-bits.ll | 38 +++++++++++++++++++ llvm/unittests/Analysis/ValueTrackingTest.cpp | 2 +- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 2d1486d252c3..063162ed38ba 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4940,11 +4940,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, // subnormal input could produce a negative zero output. const Function *F = II->getFunction(); if (Q.IIQ.hasNoSignedZeros(II) || - (F && KnownSrc.isKnownNeverLogicalNegZero(*F, II->getType()))) { + (F && KnownSrc.isKnownNeverLogicalNegZero(*F, II->getType()))) Known.knownNot(fcNegZero); - if (KnownSrc.isKnownNeverNaN()) - Known.signBitMustBeZero(); - } break; } diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index 82cd24027e4e..41b16f3333c1 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -1698,6 +1698,44 @@ define i32 @test_none(float nofpclass(all) %x) { ret i32 %and } +; We cannot make assumptions about the sign of result of sqrt +; when the input is a negative value (except for -0). +define i1 @pr92217() { +; CHECK-LABEL: @pr92217( +; CHECK-NEXT: [[X:%.*]] = call float @llvm.sqrt.f32(float 0xC6DEBE9E60000000) +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X]] to i32 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[Y]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; + %x = call float @llvm.sqrt.f32(float 0xC6DEBE9E60000000) + %y = bitcast float %x to i32 + %cmp = icmp slt i32 %y, 0 + ret i1 %cmp +} + +define i1 @sqrt_negative_input(float nofpclass(nan zero pnorm psub pinf) %a) { +; CHECK-LABEL: @sqrt_negative_input( +; CHECK-NEXT: [[X:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]]) +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X]] to i32 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[Y]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; + %x = call float @llvm.sqrt.f32(float %a) + %y = bitcast float %x to i32 + %cmp = icmp slt i32 %y, 0 + ret i1 %cmp +} + +define i1 @sqrt_negative_input_nnan(float nofpclass(nan zero pnorm psub pinf) %a) { +; CHECK-LABEL: @sqrt_negative_input_nnan( +; CHECK-NEXT: ret i1 false +; + %x = call nnan float @llvm.sqrt.f32(float %a) + %y = bitcast float %x to i32 + %cmp = icmp slt i32 %y, 0 + ret i1 %cmp +} + define i8 @test_icmp_add(i8 %n, i8 %n2, i8 %other) { ; CHECK-LABEL: @test_icmp_add( ; CHECK-NEXT: entry: diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp index 8738af91b652..a30db468c772 100644 --- a/llvm/unittests/Analysis/ValueTrackingTest.cpp +++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp @@ -2005,7 +2005,7 @@ TEST_F(ComputeKnownFPClassTest, SqrtNszSignBit) { computeKnownFPClass(A4, M->getDataLayout(), fcAllFlags, 0, nullptr, nullptr, nullptr, nullptr, /*UseInstrInfo=*/true); EXPECT_EQ(fcPositive | fcQNan, UseInstrInfoNSZNoNan.KnownFPClasses); - EXPECT_EQ(false, UseInstrInfoNSZNoNan.SignBit); + EXPECT_EQ(std::nullopt, UseInstrInfoNSZNoNan.SignBit); KnownFPClass NoUseInstrInfoNSZNoNan = computeKnownFPClass(A4, M->getDataLayout(), fcAllFlags, 0, nullptr, -- GitLab From d108fa03d4ac1a2634fa0a1e9b3058f4196f261c Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Mon, 20 May 2024 14:53:22 +0100 Subject: [PATCH 084/793] [LAA] Add tests with invariant accesses using vector types. Extra tests for https://github.com/llvm/llvm-project/pull/92307 --- .../invariant-dependence-before.ll | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/llvm/test/Analysis/LoopAccessAnalysis/invariant-dependence-before.ll b/llvm/test/Analysis/LoopAccessAnalysis/invariant-dependence-before.ll index 2a210a5a445b..1e16d89f6917 100644 --- a/llvm/test/Analysis/LoopAccessAnalysis/invariant-dependence-before.ll +++ b/llvm/test/Analysis/LoopAccessAnalysis/invariant-dependence-before.ll @@ -754,3 +754,73 @@ loop: exit: ret void } + +define void @test_invar_vector_dependence_before_positive_strided_access_1(ptr %a) { +; CHECK-LABEL: 'test_invar_vector_dependence_before_positive_strided_access_1' +; CHECK-NEXT: loop: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Unknown data dependence. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Unknown: +; CHECK-NEXT: %l = load <4 x i8>, ptr %a, align 4 -> +; CHECK-NEXT: store i32 0, ptr %gep, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; +entry: + %gep.off = getelementptr i8, ptr %a, i32 4 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load <4 x i8>, ptr %a + store i32 0, ptr %gep + %iv.next = add i32 %iv, 1 + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} + +define void @test_invar_scalable_dependence_before_positive_strided_access_1(ptr %a) { +; CHECK-LABEL: 'test_invar_scalable_dependence_before_positive_strided_access_1' +; CHECK-NEXT: loop: +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Unknown data dependence. +; CHECK-NEXT: Dependences: +; CHECK-NEXT: Unknown: +; CHECK-NEXT: %l = load , ptr %a, align 4 -> +; CHECK-NEXT: store i32 0, ptr %gep, align 4 +; CHECK-EMPTY: +; CHECK-NEXT: Run-time memory checks: +; CHECK-NEXT: Grouped accesses: +; CHECK-EMPTY: +; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop. +; CHECK-NEXT: SCEV assumptions: +; CHECK-EMPTY: +; CHECK-NEXT: Expressions re-written: +; +entry: + %gep.off = getelementptr i8, ptr %a, i32 4 + br label %loop + +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %gep = getelementptr i32, ptr %gep.off, i32 %iv + %l = load , ptr %a + store i32 0, ptr %gep + %iv.next = add i32 %iv, 1 + %ec = icmp eq i32 %iv.next, 100 + br i1 %ec, label %exit, label %loop + +exit: + ret void +} -- GitLab From 1553b21f6d3b620b8e32121b974793342820ab8c Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 20 May 2024 16:11:15 +0200 Subject: [PATCH 085/793] [clang] CTAD alias: Fix missing template arg packs during the transformation (#92535) clang rejects some valid code (see testcases) because of an incorrect transformed deduction guides. This patch fixes it. We miss the template argument packs during the transformation (`auto (type-parameter-0-0...) -> Foo<>`). In `TreeTransform::TransformTemplateArguments `, we have a logic of handling template argument packs which were originally added to support CTAD alias, it doesn't seem to be needed, we need to unpack them. --- clang/lib/Sema/TreeTransform.h | 8 -------- clang/test/AST/ast-dump-ctad-alias.cpp | 20 ++++++++++++++++++++ clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 5 +++++ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index b10e5ba65eb1..f9fec21bf5bb 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4818,14 +4818,6 @@ bool TreeTransform::TransformTemplateArguments( TemplateArgumentLoc In = *First; if (In.getArgument().getKind() == TemplateArgument::Pack) { - // When building the deduction guides, we rewrite the argument packs - // instead of unpacking. - if (getSema().CodeSynthesisContexts.back().Kind == - Sema::CodeSynthesisContext::BuildingDeductionGuides) { - if (getDerived().TransformTemplateArgument(In, Out, Uneval)) - return true; - continue; - } // Unpack argument packs, which we translate them into separate // arguments. // FIXME: We could do much better if we could guarantee that the diff --git a/clang/test/AST/ast-dump-ctad-alias.cpp b/clang/test/AST/ast-dump-ctad-alias.cpp index 7fe6c05621ee..9382558393e4 100644 --- a/clang/test/AST/ast-dump-ctad-alias.cpp +++ b/clang/test/AST/ast-dump-ctad-alias.cpp @@ -48,3 +48,23 @@ Out2::AInner t(1.0); // CHECK-NEXT: | |-TemplateArgument type 'double' // CHECK-NEXT: | | `-BuiltinType {{.*}} 'double' // CHECK-NEXT: | `-ParmVarDecl {{.*}} 'double' + +template +struct Foo { + Foo(T1...); +}; + +template +using AFoo = Foo; +AFoo a(1, 2); +// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (type-parameter-0-0...) -> Foo' +// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'type-parameter-0-0...' pack +// CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (int, int) -> Foo' implicit_instantiation + +template +using BFoo = Foo; +BFoo b2(1.0, 2.0); +// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (type-parameter-0-0, type-parameter-0-0) -> Foo' +// CHECK-NEXT: | | |-ParmVarDecl {{.*}} 'type-parameter-0-0' +// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'type-parameter-0-0' +// CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (double, double) -> Foo' implicit_instantiation diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 285532e3d80d..4c6ef5adae7d 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -173,6 +173,11 @@ template using AFoo = Foo; auto b = AFoo{}; +AFoo a(1, 2); + +template +using BFoo = Foo; +BFoo b2(1.0, 2.0); } // namespace test13 namespace test14 { -- GitLab From d0dc29c2084a18c33b1b5b1cad9fd42215869746 Mon Sep 17 00:00:00 2001 From: jofrn Date: Mon, 20 May 2024 06:18:49 -0800 Subject: [PATCH 086/793] [TableGen] HasOneUse builtin predicate on PatFrags (#91578) This predicate tells GlobalISelEmitter and DAGISelEmitter to check that the instruction to emit has only one use of its result. This can be used on a PatFrag instead of defining custom predicates for both emitters per record that requires it. --- .../CodeGen/GlobalISel/GIMatchTableExecutor.h | 4 +++ .../GlobalISel/GIMatchTableExecutorImpl.h | 17 +++++++++++ .../include/llvm/Target/TargetSelectionDAG.td | 3 ++ llvm/test/TableGen/predicate-patfags.td | 30 ++++++++++++++----- .../TableGen/Common/CodeGenDAGPatterns.cpp | 7 ++++- .../TableGen/Common/CodeGenDAGPatterns.h | 2 ++ .../Common/GlobalISel/GlobalISelMatchTable.h | 23 ++++++++++++++ llvm/utils/TableGen/GlobalISelEmitter.cpp | 6 +++- 8 files changed, 82 insertions(+), 10 deletions(-) diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h index 371c5c5a0a1e..cc2dd2f4e489 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h @@ -212,6 +212,10 @@ enum { /// - InsnID(ULEB128) - Instruction ID GIM_CheckHasNoUse, + /// Check if there's one use of the first result. + /// - InsnID(ULEB128) - Instruction ID + GIM_CheckHasOneUse, + /// Check the type for the specified operand /// - InsnID(ULEB128) - Instruction ID /// - OpIdx(ULEB128) - Operand index diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h index 2ea9d11779f0..05f1a7e57e56 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h @@ -468,7 +468,24 @@ bool GIMatchTableExecutor::executeMatchTable( if (handleReject() == RejectAndGiveUp) return false; } + break; + } + case GIM_CheckHasOneUse: { + uint64_t InsnID = readULEB(); + + DEBUG_WITH_TYPE(TgtExecutor::getName(), + dbgs() << CurrentIdx << ": GIM_CheckHasOneUse(MIs[" + << InsnID << "]\n"); + + const MachineInstr *MI = State.MIs[InsnID]; + assert(MI && "Used insn before defined"); + assert(MI->getNumDefs() > 0 && "No defs"); + const Register Res = MI->getOperand(0).getReg(); + if (!MRI.hasOneNonDBGUse(Res)) { + if (handleReject() == RejectAndGiveUp) + return false; + } break; } case GIM_CheckAtomicOrdering: { diff --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td index 1684b424e3b4..1c95a6090984 100644 --- a/llvm/include/llvm/Target/TargetSelectionDAG.td +++ b/llvm/include/llvm/Target/TargetSelectionDAG.td @@ -884,6 +884,9 @@ class PatFrags frags, code pred = [{}], // If set to true, a predicate is added that checks for the absence of use of // the first result. bit HasNoUse = ?; + // If set to true, a predicate is added that checks for the sole use of + // the first result. + bit HasOneUse = ?; // Is the desired pre-packaged predicate for a load? bit IsLoad = ?; diff --git a/llvm/test/TableGen/predicate-patfags.td b/llvm/test/TableGen/predicate-patfags.td index 2cf29769dc13..39133f324f30 100644 --- a/llvm/test/TableGen/predicate-patfags.td +++ b/llvm/test/TableGen/predicate-patfags.td @@ -1,5 +1,7 @@ -// RUN: llvm-tblgen -gen-dag-isel -I %p/../../include -I %p/Common %s 2>&1 | FileCheck -check-prefix=SDAG %s -// RUN: llvm-tblgen -gen-global-isel -I %p/../../include -I %p/Common %s 2>&1 | FileCheck -check-prefix=GISEL %s +// RUN: llvm-tblgen -gen-dag-isel -I %p/../../include -I %p/Common %s 2>&1 | FileCheck -check-prefixes=SDAG,SCUSTOM %s +// RUN: llvm-tblgen -gen-dag-isel -I %p/../../include -I %p/Common %s -DHASONEUSE 2>&1 | FileCheck -check-prefixes=SDAG,SBUILTIN %s +// RUN: llvm-tblgen -gen-global-isel -I %p/../../include -I %p/Common %s 2>&1 | FileCheck -check-prefixes=GISEL,GCUSTOM %s +// RUN: llvm-tblgen -gen-global-isel -I %p/../../include -I %p/Common %s -DHASONEUSE 2>&1 | FileCheck -check-prefixes=GISEL,GBUILTIN %s include "llvm/Target/Target.td" include "GlobalISelEmitterCommon.td" @@ -31,11 +33,16 @@ def : GINodeEquiv; def TGTmul24_oneuse : PatFrag< (ops node:$src0, node:$src1), - (TGTmul24 $src0, $src1), - [{ return N->hasOneUse(); }]> { + (TGTmul24 $src0, $src1) +#ifndef HASONEUSE + , [{ return N->hasOneUse(); }]> { let GISelPredicateCode = [{ return MRI->hasOneNonDBGUse(MI.getOperand(0).getReg()); }]; +#else + > { + let HasOneUse = 1; +#endif } // SDAG: OPC_CheckOpcode, TARGET_VAL(ISD::INTRINSIC_W_CHAIN), @@ -44,19 +51,26 @@ def TGTmul24_oneuse : PatFrag< // SDAG: OPC_CheckOpcode, TARGET_VAL(TargetISD::MUL24), // SDAG: OPC_CheckPredicate0, // Predicate_TGTmul24_oneuse +// SCUSTOM: return N->hasOneUse(); +// SBUILTIN: if (!SDValue(N, 0).hasOneUse()) return false; + // GISEL: GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS), // GISEL: GIM_CheckIntrinsicID, /*MI*/1, /*Op*/1, GIMT_Encode2(Intrinsic::tgt_mul24), -// GISEL: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_TGTmul24_oneuse), +// GBUILTIN: GIM_CheckHasOneUse, /*MI*/1, +// GCUSTOM: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_TGTmul24_oneuse), // GISEL: GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS), // GISEL: GIM_CheckIntrinsicID, /*MI*/1, /*Op*/1, GIMT_Encode2(Intrinsic::tgt_mul24), -// GISEL: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_TGTmul24_oneuse), +// GBUILTIN: GIM_CheckHasOneUse, /*MI*/1, +// GCUSTOM: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_TGTmul24_oneuse), // GISEL: GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(MyTarget::G_TGT_MUL24), -// GISEL: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_TGTmul24_oneuse), +// GBUILTIN: GIM_CheckHasOneUse, /*MI*/1, +// GCUSTOM: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_TGTmul24_oneuse), // GISEL: GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(MyTarget::G_TGT_MUL24), -// GISEL: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_TGTmul24_oneuse), +// GBUILTIN: GIM_CheckHasOneUse, /*MI*/1, +// GCUSTOM: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_TGTmul24_oneuse), def inst_mad24 : I< (outs GPR32:$dst), (ins GPR32:$src0, GPR32:$src1, GPR32:$src2), diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp index 88d353e89a46..709aa00ae8b3 100644 --- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp @@ -903,7 +903,7 @@ TreePredicateFn::TreePredicateFn(TreePattern *N) : PatFragRec(N) { } bool TreePredicateFn::hasPredCode() const { - return isLoad() || isStore() || isAtomic() || hasNoUse() || + return isLoad() || isStore() || isAtomic() || hasNoUse() || hasOneUse() || !PatFragRec->getRecord()->getValueAsString("PredicateCode").empty(); } @@ -1140,6 +1140,8 @@ std::string TreePredicateFn::getPredCode() const { if (hasNoUse()) Code += "if (!SDValue(N, 0).use_empty()) return false;\n"; + if (hasOneUse()) + Code += "if (!SDValue(N, 0).hasOneUse()) return false;\n"; std::string PredicateCode = std::string(PatFragRec->getRecord()->getValueAsString("PredicateCode")); @@ -1187,6 +1189,9 @@ bool TreePredicateFn::usesOperands() const { bool TreePredicateFn::hasNoUse() const { return isPredefinedPredicateEqualTo("HasNoUse", true); } +bool TreePredicateFn::hasOneUse() const { + return isPredefinedPredicateEqualTo("HasOneUse", true); +} bool TreePredicateFn::isLoad() const { return isPredefinedPredicateEqualTo("IsLoad", true); } diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h index 7f94db0b7d5d..1f4d45d81fd3 100644 --- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h +++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h @@ -533,6 +533,8 @@ public: // Check if the HasNoUse predicate is set. bool hasNoUse() const; + // Check if the HasOneUse predicate is set. + bool hasOneUse() const; // Is the desired predefined predicate for a load? bool isLoad() const; diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h index 5fe3f9a32c01..edddc051c162 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h @@ -806,6 +806,7 @@ public: IPM_MemoryAlignment, IPM_VectorSplatImm, IPM_NoUse, + IPM_OneUse, IPM_GenericPredicate, IPM_MIFlags, OPM_SameOperand, @@ -1691,6 +1692,28 @@ public: } }; +/// Generates code to check that the first result has only one use. +class OneUsePredicateMatcher : public InstructionPredicateMatcher { +public: + OneUsePredicateMatcher(unsigned InsnVarID) + : InstructionPredicateMatcher(IPM_OneUse, InsnVarID) {} + + static bool classof(const PredicateMatcher *P) { + return P->getKind() == IPM_OneUse; + } + + bool isIdentical(const PredicateMatcher &B) const override { + return InstructionPredicateMatcher::isIdentical(B); + } + + void emitPredicateOpcodes(MatchTable &Table, + RuleMatcher &Rule) const override { + Table << MatchTable::Opcode("GIM_CheckHasOneUse") + << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) + << MatchTable::LineBreak; + } +}; + /// Generates code to check that a set of predicates and operands match for a /// particular instruction. /// diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index 9b356148cc17..ec41cd9fec07 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -207,7 +207,7 @@ static Error isTrivialOperatorNode(const TreePatternNode &N) { if (Predicate.isImmediatePattern()) continue; - if (Predicate.hasNoUse()) + if (Predicate.hasNoUse() || Predicate.hasOneUse()) continue; if (Predicate.isNonExtLoad() || Predicate.isAnyExtLoad() || @@ -782,6 +782,10 @@ Expected GlobalISelEmitter::createAndImportSelDAGMatcher( InsnMatcher.addPredicate(); HasAddedBuiltinMatcher = true; } + if (Predicate.hasOneUse()) { + InsnMatcher.addPredicate(); + HasAddedBuiltinMatcher = true; + } if (Predicate.hasGISelPredicateCode()) { if (Predicate.usesOperands()) { -- GitLab From 64e0835126d1cf3d36eb31fa1ebb4e286cc3bea7 Mon Sep 17 00:00:00 2001 From: Andrew Ng Date: Mon, 20 May 2024 15:29:24 +0100 Subject: [PATCH 087/793] [clang] Make PS template DLL attribute propagation the same as MSVC (#92549) For PlayStation, make the propagation of DLL import/export attributes for explicit template instantiations the same as MSVC and Windows Itanium. --- clang/lib/Sema/SemaTemplate.cpp | 6 ++---- ...licit-dllexport-template-specialization.cpp | 13 +++++-------- .../CodeGenCXX/windows-itanium-dllexport.cpp | 18 +++++++----------- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 4937cce4621f..8a7af678b33d 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -11124,8 +11124,7 @@ DeclResult Sema::ActOnExplicitInstantiation( Def->setTemplateSpecializationKind(TSK); if (!getDLLAttr(Def) && getDLLAttr(Specialization) && - (Context.getTargetInfo().shouldDLLImportComdatSymbols() && - !Context.getTargetInfo().getTriple().isPS())) { + Context.getTargetInfo().shouldDLLImportComdatSymbols()) { // An explicit instantiation definition can add a dll attribute to a // template with a previous instantiation declaration. MinGW doesn't // allow this. @@ -11142,8 +11141,7 @@ DeclResult Sema::ActOnExplicitInstantiation( bool NewlyDLLExported = !PreviouslyDLLExported && Specialization->hasAttr(); if (Old_TSK == TSK_ImplicitInstantiation && NewlyDLLExported && - (Context.getTargetInfo().shouldDLLImportComdatSymbols() && - !Context.getTargetInfo().getTriple().isPS())) { + Context.getTargetInfo().shouldDLLImportComdatSymbols()) { // An explicit instantiation definition can add a dll attribute to a // template with a previous implicit instantiation. MinGW doesn't allow // this. We limit clang to only adding dllexport, to avoid potentially diff --git a/clang/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp b/clang/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp index 3a5693275824..d281826ee70f 100644 --- a/clang/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp +++ b/clang/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -std=c++11 -triple i686-windows -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MS -// RUN: %clang_cc1 -std=c++11 -triple i686-windows-itanium -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-IA -// RUN: %clang_cc1 -std=c++11 -triple x86_64-scei-ps4 -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-PS4 -// RUN: %clang_cc1 -std=c++11 -triple x86_64-sie-ps5 -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-PS4 +// RUN: %clang_cc1 -std=c++11 -triple i686-windows-itanium -fdeclspec -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple x86_64-scei-ps4 -fdeclspec -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -triple x86_64-sie-ps5 -fdeclspec -emit-llvm %s -o - | FileCheck %s template struct s {}; @@ -15,8 +15,5 @@ template class __declspec(dllexport) t; // CHECK-MS: dllexport {{.*}} @"??4?$t@D@@QAEAAV0@ABV0@@Z" // CHECK-MS: dllexport {{.*}} @"??4?$s@D@@QAEAAU0@ABU0@@Z" -// CHECK-IA: dllexport {{.*}} @_ZN1tIcEaSERKS0_ -// CHECK-IA: dllexport {{.*}} @_ZN1sIcEaSERKS0_ - -// CHECK-PS4-NOT: @_ZN1tIcEaSERKS0_ -// CHECK-PS4-NOT: @_ZN1sIcEaSERKS0_ +// CHECK: dllexport {{.*}} @_ZN1tIcEaSERKS0_ +// CHECK: dllexport {{.*}} @_ZN1sIcEaSERKS0_ diff --git a/clang/test/CodeGenCXX/windows-itanium-dllexport.cpp b/clang/test/CodeGenCXX/windows-itanium-dllexport.cpp index c09fa30d761a..334cebff99da 100644 --- a/clang/test/CodeGenCXX/windows-itanium-dllexport.cpp +++ b/clang/test/CodeGenCXX/windows-itanium-dllexport.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -emit-llvm -triple i686-windows-itanium -fdeclspec %s -o - | FileCheck %s --check-prefixes=CHECK,WI -// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps4 -fdeclspec %s -o - | FileCheck %s --check-prefixes=CHECK,PS4 -// RUN: %clang_cc1 -emit-llvm -triple x86_64-sie-ps5 -fdeclspec %s -o - | FileCheck %s --check-prefixes=CHECK,PS4 +// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps4 -fdeclspec %s -o - | FileCheck %s --check-prefixes=CHECK,PS +// RUN: %clang_cc1 -emit-llvm -triple x86_64-sie-ps5 -fdeclspec %s -o - | FileCheck %s --check-prefixes=CHECK,PS #define JOIN2(x, y) x##y #define JOIN(x, y) JOIN2(x, y) @@ -27,18 +27,14 @@ template class __declspec(dllexport) c; extern template class c; template class __declspec(dllexport) c; -// WI: define {{.*}} dllexport {{.*}} @_ZN1cIcEaSERKS0_ -// WI: define {{.*}} dllexport {{.*}} @_ZN1cIcE1fEv -// PS4-NOT: @_ZN1cIcEaSERKS0_ -// PS4: define weak_odr void @_ZN1cIcE1fEv +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcEaSERKS0_ +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcE1fEv c g; template class __declspec(dllexport) c; -// WI: define {{.*}} dllexport {{.*}} @_ZN1cIdEaSERKS0_ -// WI: define {{.*}} dllexport {{.*}} @_ZN1cIdE1fEv -// PS4-NOT: @_ZN1cIdEaSERKS0_ -// PS4: define weak_odr void @_ZN1cIdE1fEv +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdEaSERKS0_ +// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdE1fEv template struct outer { @@ -59,4 +55,4 @@ USEMEMFUNC(outer::inner, f) // CHECK-DAG: declare dllimport {{.*}} @_ZN5outerIcE1fEv // WI-DAG: define {{.*}} @_ZN5outerIcE5inner1fEv -// PS4-DAG: declare {{.*}} @_ZN5outerIcE5inner1fEv +// PS-DAG: declare {{.*}} @_ZN5outerIcE5inner1fEv -- GitLab From c2f92a33464bd9b76007ad5817952000add0033e Mon Sep 17 00:00:00 2001 From: Shan Huang <52285902006@stu.ecnu.edu.cn> Date: Mon, 20 May 2024 22:32:04 +0800 Subject: [PATCH 088/793] [DebugInfo][NaryReassociate] Fix missing debug location updates (#92545) Fixes #92537 --- .../lib/Transforms/Scalar/NaryReassociate.cpp | 1 + .../preserving-debugloc-add-mul.ll | 69 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 llvm/test/Transforms/NaryReassociate/preserving-debugloc-add-mul.ll diff --git a/llvm/lib/Transforms/Scalar/NaryReassociate.cpp b/llvm/lib/Transforms/Scalar/NaryReassociate.cpp index 308622615332..224cd24915fa 100644 --- a/llvm/lib/Transforms/Scalar/NaryReassociate.cpp +++ b/llvm/lib/Transforms/Scalar/NaryReassociate.cpp @@ -519,6 +519,7 @@ Instruction *NaryReassociatePass::tryReassociatedBinaryOp(const SCEV *LHSExpr, default: llvm_unreachable("Unexpected instruction."); } + NewI->setDebugLoc(I->getDebugLoc()); NewI->takeName(I); return NewI; } diff --git a/llvm/test/Transforms/NaryReassociate/preserving-debugloc-add-mul.ll b/llvm/test/Transforms/NaryReassociate/preserving-debugloc-add-mul.ll new file mode 100644 index 000000000000..cc66d0cd3710 --- /dev/null +++ b/llvm/test/Transforms/NaryReassociate/preserving-debugloc-add-mul.ll @@ -0,0 +1,69 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -passes=nary-reassociate -S | FileCheck %s + +; Test that NaryReassociate's tryReassociatedBinaryOp() propagates the +; debug location to new `add` and `mul` from the original binary operator +; they replaced (`%3` in both `@add_reassociate` and `@mul_reassociate`). + +define void @add_reassociate(i32 %a, i32 %b, i32 %c) !dbg !5 { +; CHECK-LABEL: define void @add_reassociate( +; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]]) !dbg [[DBG5:![0-9]+]] { +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[A]], [[C]] +; CHECK-NEXT: call void @foo(i32 [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], [[B]], !dbg [[DBG8:![0-9]+]] +; CHECK-NEXT: call void @foo(i32 [[TMP2]]) +; CHECK-NEXT: ret void +; + %1 = add i32 %a, %c + call void @foo(i32 %1) + %2 = add i32 %b, %c + %3 = add i32 %a, %2, !dbg !11 + call void @foo(i32 %3) + ret void +} + +define void @mul_reassociate(i32 %a, i32 %b, i32 %c) !dbg !14 { +; CHECK-LABEL: define void @mul_reassociate( +; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]]) !dbg [[DBG9:![0-9]+]] { +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[A]], [[C]] +; CHECK-NEXT: call void @foo(i32 [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = mul i32 [[TMP1]], [[B]], !dbg [[DBG10:![0-9]+]] +; CHECK-NEXT: call void @foo(i32 [[TMP2]]) +; CHECK-NEXT: ret void +; + %1 = mul i32 %a, %c + call void @foo(i32 %1) + %2 = mul i32 %a, %b + %3 = mul i32 %2, %c, !dbg !18 + call void @foo(i32 %3) + ret void +} + +declare void @foo(i32) + +!llvm.dbg.cu = !{!0} +!llvm.debugify = !{!2, !3} +!llvm.module.flags = !{!4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug) +!1 = !DIFile(filename: "test.ll", directory: "/") +!2 = !{i32 12} +!3 = !{i32 0} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = distinct !DISubprogram(name: "add_reassociate", linkageName: "add_reassociate", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!6 = !DISubroutineType(types: !7) +!7 = !{} +!11 = !DILocation(line: 4, column: 1, scope: !5) +!14 = distinct !DISubprogram(name: "mul_reassociate", linkageName: "mul_reassociate", scope: null, file: !1, line: 7, type: !6, scopeLine: 7, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!18 = !DILocation(line: 10, column: 1, scope: !14) + +;. +; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C, file: [[META1:![0-9]+]], producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug) +; CHECK: [[META1]] = !DIFile(filename: "test.ll", directory: {{.*}}) +; CHECK: [[DBG5]] = distinct !DISubprogram(name: "add_reassociate", linkageName: "add_reassociate", scope: null, file: [[META1]], line: 1, type: [[META6:![0-9]+]], scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]]) +; CHECK: [[META6]] = !DISubroutineType(types: [[META7:![0-9]+]]) +; CHECK: [[META7]] = !{} +; CHECK: [[DBG8]] = !DILocation(line: 4, column: 1, scope: [[DBG5]]) +; CHECK: [[DBG9]] = distinct !DISubprogram(name: "mul_reassociate", linkageName: "mul_reassociate", scope: null, file: [[META1]], line: 7, type: [[META6]], scopeLine: 7, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]]) +; CHECK: [[DBG10]] = !DILocation(line: 10, column: 1, scope: [[DBG9]]) +;. -- GitLab From 60fe1e9e657180cc66dc5b1211b06144f010852b Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Mon, 20 May 2024 07:51:11 -0700 Subject: [PATCH 089/793] [clang] Use SmallString::str (NFC) (#92717) --- clang/lib/ARCMigrate/ARCMT.cpp | 3 +-- clang/lib/ARCMigrate/ObjCMT.cpp | 3 +-- clang/lib/Sema/SemaExpr.cpp | 4 +--- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/clang/lib/ARCMigrate/ARCMT.cpp b/clang/lib/ARCMigrate/ARCMT.cpp index b410d5f3b42a..5835559bff6b 100644 --- a/clang/lib/ARCMigrate/ARCMT.cpp +++ b/clang/lib/ARCMigrate/ARCMT.cpp @@ -606,8 +606,7 @@ bool MigrationProcess::applyTransform(TransformFn trans, llvm::raw_svector_ostream vecOS(newText); buf.write(vecOS); std::unique_ptr memBuf( - llvm::MemoryBuffer::getMemBufferCopy( - StringRef(newText.data(), newText.size()), newFname)); + llvm::MemoryBuffer::getMemBufferCopy(newText.str(), newFname)); SmallString<64> filePath(file->getName()); Unit->getFileManager().FixupRelativePath(filePath); Remapper.remap(filePath.str(), std::move(memBuf)); diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp index aaf41dc4039c..4357c8e3f09a 100644 --- a/clang/lib/ARCMigrate/ObjCMT.cpp +++ b/clang/lib/ARCMigrate/ObjCMT.cpp @@ -1963,8 +1963,7 @@ void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) { llvm::raw_svector_ostream vecOS(newText); buf.write(vecOS); std::unique_ptr memBuf( - llvm::MemoryBuffer::getMemBufferCopy( - StringRef(newText.data(), newText.size()), file->getName())); + llvm::MemoryBuffer::getMemBufferCopy(newText.str(), file->getName())); SmallString<64> filePath(file->getName()); FileMgr.FixupRelativePath(filePath); Remapper.remap(filePath.str(), std::move(memBuf)); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5ecfdee21f09..f2d0a93d9a1e 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3718,9 +3718,7 @@ static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal, APFloat::getSmallest(Format).toString(buffer); } - S.Diag(Loc, diagnostic) - << Ty - << StringRef(buffer.data(), buffer.size()); + S.Diag(Loc, diagnostic) << Ty << buffer.str(); } bool isExact = (result == APFloat::opOK); -- GitLab From 2a90d59fc3905d3d56dac99fa25640a6d6a7bad2 Mon Sep 17 00:00:00 2001 From: Hubert Tong Date: Mon, 20 May 2024 10:54:49 -0400 Subject: [PATCH 090/793] [libcxx] locale.cpp: Move build_name helper into unnamed namespace (#92461) Fix linkage of `build_name`; it is not supposed to have external linkage. --- libcxx/src/locale.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcxx/src/locale.cpp b/libcxx/src/locale.cpp index 1ca88e30f63a..c5ab6de5d657 100644 --- a/libcxx/src/locale.cpp +++ b/libcxx/src/locale.cpp @@ -102,8 +102,6 @@ inline constexpr size_t countof(const T* const begin, const T* const end) { return static_cast(end - begin); } -} // namespace - string build_name(const string& other, const string& one, locale::category c) { if (other == "*" || one == "*") return "*"; @@ -115,6 +113,8 @@ string build_name(const string& other, const string& one, locale::category c) { return "*"; } +} // namespace + const locale::category locale::none; const locale::category locale::collate; const locale::category locale::ctype; -- GitLab From 3df7cb9ab9d2cc347efd5748dfc81fdb2082e529 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Mon, 20 May 2024 08:23:11 -0500 Subject: [PATCH 091/793] [Offload] Remove unused version script for plugins Summary: The plugins are no longer linked to a share library, making this unused and useless. --- offload/plugins-nextgen/exports | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 offload/plugins-nextgen/exports diff --git a/offload/plugins-nextgen/exports b/offload/plugins-nextgen/exports deleted file mode 100644 index cc7beda183af..000000000000 --- a/offload/plugins-nextgen/exports +++ /dev/null @@ -1,6 +0,0 @@ -VERS1.0 { - global: - __tgt_rtl*; - local: - *; -}; -- GitLab From 02f1a992035f40b49435f0e7f358badd152d9dc2 Mon Sep 17 00:00:00 2001 From: Krzysztof Drewniak Date: Mon, 20 May 2024 10:28:20 -0500 Subject: [PATCH 092/793] [DivRemPairs] Pre-commit tests for PR #92627 (#92628) The tests are added to a new AMDGPU/ subdirectory since I found the missed optimization while hacking on AMDGPU code. Also, this ensures that AMDGPU, which uses DivRemPass, is being checked for existing expected behavior. --- .../DivRemPairs/AMDGPU/div-rem-pairs.ll | 141 ++++++++++++++++++ .../DivRemPairs/AMDGPU/lit.local.cfg | 2 + 2 files changed, 143 insertions(+) create mode 100644 llvm/test/Transforms/DivRemPairs/AMDGPU/div-rem-pairs.ll create mode 100644 llvm/test/Transforms/DivRemPairs/AMDGPU/lit.local.cfg diff --git a/llvm/test/Transforms/DivRemPairs/AMDGPU/div-rem-pairs.ll b/llvm/test/Transforms/DivRemPairs/AMDGPU/div-rem-pairs.ll new file mode 100644 index 000000000000..bd7a20a98539 --- /dev/null +++ b/llvm/test/Transforms/DivRemPairs/AMDGPU/div-rem-pairs.ll @@ -0,0 +1,141 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -passes=div-rem-pairs -S -mtriple=amdgcn-amd-amdhsa | FileCheck %s + +define i32 @basic(ptr %p, i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @basic( +; CHECK-SAME: ptr [[P:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[X_FROZEN:%.*]] = freeze i32 [[X]] +; CHECK-NEXT: [[Y_FROZEN:%.*]] = freeze i32 [[Y]] +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X_FROZEN]], [[Y_FROZEN]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y_FROZEN]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X_FROZEN]], [[TMP1]] +; CHECK-NEXT: store i32 [[DIV]], ptr [[P]], align 4 +; CHECK-NEXT: ret i32 [[REM_DECOMPOSED]] +; + %div = udiv i32 %x, %y + %rem = urem i32 %x, %y + store i32 %div, ptr %p, align 4 + ret i32 %rem +} + +define i32 @no_freezes(ptr %p, i32 noundef %x, i32 noundef %y) { +; CHECK-LABEL: define i32 @no_freezes( +; CHECK-SAME: ptr [[P:%.*]], i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) { +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X]], [[Y]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X]], [[TMP1]] +; CHECK-NEXT: store i32 [[DIV]], ptr [[P]], align 4 +; CHECK-NEXT: ret i32 [[REM_DECOMPOSED]] +; + %div = udiv i32 %x, %y + %rem = urem i32 %x, %y + store i32 %div, ptr %p, align 4 + ret i32 %rem +} + +; FIXME: There should be no need to `freeze` x2 and y2 since they have defined +; but potentially poison values. +define i32 @poison_does_not_freeze(ptr %p, i32 noundef %x, i32 noundef %y) { +; CHECK-LABEL: define i32 @poison_does_not_freeze( +; CHECK-SAME: ptr [[P:%.*]], i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) { +; CHECK-NEXT: [[X2:%.*]] = shl nuw nsw i32 [[X]], 5 +; CHECK-NEXT: [[Y2:%.*]] = add nuw nsw i32 [[Y]], 1 +; CHECK-NEXT: [[X2_FROZEN:%.*]] = freeze i32 [[X2]] +; CHECK-NEXT: [[Y2_FROZEN:%.*]] = freeze i32 [[Y2]] +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X2_FROZEN]], [[Y2_FROZEN]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2_FROZEN]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X2_FROZEN]], [[TMP1]] +; CHECK-NEXT: store i32 [[DIV]], ptr [[P]], align 4 +; CHECK-NEXT: ret i32 [[REM_DECOMPOSED]] +; + %x2 = shl nuw nsw i32 %x, 5 + %y2 = add nuw nsw i32 %y, 1 + %div = udiv i32 %x2, %y2 + %rem = urem i32 %x2, %y2 + store i32 %div, ptr %p, align 4 + ret i32 %rem +} + +define i32 @poison_does_not_freeze_signed(ptr %p, i32 noundef %x, i32 noundef %y) { +; CHECK-LABEL: define i32 @poison_does_not_freeze_signed( +; CHECK-SAME: ptr [[P:%.*]], i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) { +; CHECK-NEXT: [[X2:%.*]] = shl nuw nsw i32 [[X]], 5 +; CHECK-NEXT: [[Y2:%.*]] = add nuw nsw i32 [[Y]], 1 +; CHECK-NEXT: [[X2_FROZEN:%.*]] = freeze i32 [[X2]] +; CHECK-NEXT: [[Y2_FROZEN:%.*]] = freeze i32 [[Y2]] +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X2_FROZEN]], [[Y2_FROZEN]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2_FROZEN]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X2_FROZEN]], [[TMP1]] +; CHECK-NEXT: store i32 [[DIV]], ptr [[P]], align 4 +; CHECK-NEXT: ret i32 [[REM_DECOMPOSED]] +; + %x2 = shl nuw nsw i32 %x, 5 + %y2 = add nuw nsw i32 %y, 1 + %div = sdiv i32 %x2, %y2 + %rem = srem i32 %x2, %y2 + store i32 %div, ptr %p, align 4 + ret i32 %rem +} + +define <4 x i8> @poison_does_not_freeze_vector(ptr %p, <4 x i8> noundef %x, <4 x i8> noundef %y) { +; CHECK-LABEL: define <4 x i8> @poison_does_not_freeze_vector( +; CHECK-SAME: ptr [[P:%.*]], <4 x i8> noundef [[X:%.*]], <4 x i8> noundef [[Y:%.*]]) { +; CHECK-NEXT: [[X2:%.*]] = shl nuw nsw <4 x i8> [[X]], +; CHECK-NEXT: [[Y2:%.*]] = add nuw nsw <4 x i8> [[Y]], +; CHECK-NEXT: [[X2_FROZEN:%.*]] = freeze <4 x i8> [[X2]] +; CHECK-NEXT: [[Y2_FROZEN:%.*]] = freeze <4 x i8> [[Y2]] +; CHECK-NEXT: [[DIV:%.*]] = udiv <4 x i8> [[X2_FROZEN]], [[Y2_FROZEN]] +; CHECK-NEXT: [[TMP1:%.*]] = mul <4 x i8> [[DIV]], [[Y2_FROZEN]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub <4 x i8> [[X2_FROZEN]], [[TMP1]] +; CHECK-NEXT: store <4 x i8> [[DIV]], ptr [[P]], align 4 +; CHECK-NEXT: ret <4 x i8> [[REM_DECOMPOSED]] +; + %x2 = shl nuw nsw <4 x i8> %x, + %y2 = add nuw nsw <4 x i8> %y, + %div = udiv <4 x i8> %x2, %y2 + %rem = urem <4 x i8> %x2, %y2 + store <4 x i8> %div, ptr %p, align 4 + ret <4 x i8> %rem +} + +define i32 @explicit_poison_does_not_freeze(ptr %p, i32 noundef %y) { +; CHECK-LABEL: define i32 @explicit_poison_does_not_freeze( +; CHECK-SAME: ptr [[P:%.*]], i32 noundef [[Y:%.*]]) { +; CHECK-NEXT: [[X:%.*]] = add i32 poison, 1 +; CHECK-NEXT: [[Y2:%.*]] = add nuw nsw i32 [[Y]], 1 +; CHECK-NEXT: [[X_FROZEN:%.*]] = freeze i32 [[X]] +; CHECK-NEXT: [[Y2_FROZEN:%.*]] = freeze i32 [[Y2]] +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X_FROZEN]], [[Y2_FROZEN]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2_FROZEN]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X_FROZEN]], [[TMP1]] +; CHECK-NEXT: store i32 [[DIV]], ptr [[P]], align 4 +; CHECK-NEXT: ret i32 [[REM_DECOMPOSED]] +; + %x = add i32 poison, 1 + %y2 = add nuw nsw i32 %y, 1 + %div = udiv i32 %x, %y2 + %rem = urem i32 %x, %y2 + store i32 %div, ptr %p, align 4 + ret i32 %rem +} + +define i32 @explicit_poison_does_not_freeze_signed(ptr %p, i32 noundef %y) { +; CHECK-LABEL: define i32 @explicit_poison_does_not_freeze_signed( +; CHECK-SAME: ptr [[P:%.*]], i32 noundef [[Y:%.*]]) { +; CHECK-NEXT: [[X:%.*]] = add i32 poison, 1 +; CHECK-NEXT: [[Y2:%.*]] = add nuw nsw i32 [[Y]], 1 +; CHECK-NEXT: [[X_FROZEN:%.*]] = freeze i32 [[X]] +; CHECK-NEXT: [[Y2_FROZEN:%.*]] = freeze i32 [[Y2]] +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X_FROZEN]], [[Y2_FROZEN]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2_FROZEN]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X_FROZEN]], [[TMP1]] +; CHECK-NEXT: store i32 [[DIV]], ptr [[P]], align 4 +; CHECK-NEXT: ret i32 [[REM_DECOMPOSED]] +; + %x = add i32 poison, 1 + %y2 = add nuw nsw i32 %y, 1 + %div = sdiv i32 %x, %y2 + %rem = srem i32 %x, %y2 + store i32 %div, ptr %p, align 4 + ret i32 %rem +} diff --git a/llvm/test/Transforms/DivRemPairs/AMDGPU/lit.local.cfg b/llvm/test/Transforms/DivRemPairs/AMDGPU/lit.local.cfg new file mode 100644 index 000000000000..7c492428aec7 --- /dev/null +++ b/llvm/test/Transforms/DivRemPairs/AMDGPU/lit.local.cfg @@ -0,0 +1,2 @@ +if not "AMDGPU" in config.root.targets: + config.unsupported = True -- GitLab From 8b22bb8a62a259e35ccc49fb2f50077a2772cf2f Mon Sep 17 00:00:00 2001 From: Krzysztof Drewniak Date: Mon, 20 May 2024 10:44:18 -0500 Subject: [PATCH 093/793] [DivRemPairs] Do not freeze poisons that can't be undef (#92627) Per comments in DivRemPairs, the rewrite from ```llvm %div = div %X, %Y %rem = rem %X, %Y ``` to ```llvm %div = div %X, %Y %.mul = mul %div, %Y %rem = sub %X, %mul ``` is unsound when %X or %Y are undef. However, it is known to be sound if %X or %Y are poison but can't be undef, since both the pre- and post-rewrite %rem are `poison`. Additionally, proofs: https://alive2.llvm.org/ce/z/xtNQ8j A comment in the pass listed a TODO for changing a usage of isGuaranteedNotToBeUndefOrPoison() in the pass to something that only detects undef. Such a function has been implemented since the time that TODO was written, but has not been used. Therefore, this commit updates DivRemPairs to use isGuaranteedNotToBeUndef() instead. --- llvm/lib/Transforms/Scalar/DivRemPairs.cpp | 5 +-- .../DivRemPairs/AMDGPU/div-rem-pairs.ll | 42 +++++++------------ 2 files changed, 17 insertions(+), 30 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/DivRemPairs.cpp b/llvm/lib/Transforms/Scalar/DivRemPairs.cpp index 45f36a36b5dd..f7ada9fb8eb8 100644 --- a/llvm/lib/Transforms/Scalar/DivRemPairs.cpp +++ b/llvm/lib/Transforms/Scalar/DivRemPairs.cpp @@ -381,8 +381,7 @@ static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI, // %mul = mul %div, 1 // %mul = undef // %rem = sub %x, %mul // %rem = undef - undef = undef // If X is not frozen, %rem becomes undef after transformation. - // TODO: We need a undef-specific checking function in ValueTracking - if (!isGuaranteedNotToBeUndefOrPoison(X, nullptr, DivInst, &DT)) { + if (!isGuaranteedNotToBeUndef(X, nullptr, DivInst, &DT)) { auto *FrX = new FreezeInst(X, X->getName() + ".frozen", DivInst->getIterator()); DivInst->setOperand(0, FrX); @@ -390,7 +389,7 @@ static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI, } // Same for Y. If X = 1 and Y = (undef | 1), %rem in src is either 1 or 0, // but %rem in tgt can be one of many integer values. - if (!isGuaranteedNotToBeUndefOrPoison(Y, nullptr, DivInst, &DT)) { + if (!isGuaranteedNotToBeUndef(Y, nullptr, DivInst, &DT)) { auto *FrY = new FreezeInst(Y, Y->getName() + ".frozen", DivInst->getIterator()); DivInst->setOperand(1, FrY); diff --git a/llvm/test/Transforms/DivRemPairs/AMDGPU/div-rem-pairs.ll b/llvm/test/Transforms/DivRemPairs/AMDGPU/div-rem-pairs.ll index bd7a20a98539..d01ded9ebbfd 100644 --- a/llvm/test/Transforms/DivRemPairs/AMDGPU/div-rem-pairs.ll +++ b/llvm/test/Transforms/DivRemPairs/AMDGPU/div-rem-pairs.ll @@ -33,18 +33,14 @@ define i32 @no_freezes(ptr %p, i32 noundef %x, i32 noundef %y) { ret i32 %rem } -; FIXME: There should be no need to `freeze` x2 and y2 since they have defined -; but potentially poison values. define i32 @poison_does_not_freeze(ptr %p, i32 noundef %x, i32 noundef %y) { ; CHECK-LABEL: define i32 @poison_does_not_freeze( ; CHECK-SAME: ptr [[P:%.*]], i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) { ; CHECK-NEXT: [[X2:%.*]] = shl nuw nsw i32 [[X]], 5 ; CHECK-NEXT: [[Y2:%.*]] = add nuw nsw i32 [[Y]], 1 -; CHECK-NEXT: [[X2_FROZEN:%.*]] = freeze i32 [[X2]] -; CHECK-NEXT: [[Y2_FROZEN:%.*]] = freeze i32 [[Y2]] -; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X2_FROZEN]], [[Y2_FROZEN]] -; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2_FROZEN]] -; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X2_FROZEN]], [[TMP1]] +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X2]], [[Y2]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X2]], [[TMP1]] ; CHECK-NEXT: store i32 [[DIV]], ptr [[P]], align 4 ; CHECK-NEXT: ret i32 [[REM_DECOMPOSED]] ; @@ -61,11 +57,9 @@ define i32 @poison_does_not_freeze_signed(ptr %p, i32 noundef %x, i32 noundef %y ; CHECK-SAME: ptr [[P:%.*]], i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) { ; CHECK-NEXT: [[X2:%.*]] = shl nuw nsw i32 [[X]], 5 ; CHECK-NEXT: [[Y2:%.*]] = add nuw nsw i32 [[Y]], 1 -; CHECK-NEXT: [[X2_FROZEN:%.*]] = freeze i32 [[X2]] -; CHECK-NEXT: [[Y2_FROZEN:%.*]] = freeze i32 [[Y2]] -; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X2_FROZEN]], [[Y2_FROZEN]] -; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2_FROZEN]] -; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X2_FROZEN]], [[TMP1]] +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X2]], [[Y2]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X2]], [[TMP1]] ; CHECK-NEXT: store i32 [[DIV]], ptr [[P]], align 4 ; CHECK-NEXT: ret i32 [[REM_DECOMPOSED]] ; @@ -82,11 +76,9 @@ define <4 x i8> @poison_does_not_freeze_vector(ptr %p, <4 x i8> noundef %x, <4 x ; CHECK-SAME: ptr [[P:%.*]], <4 x i8> noundef [[X:%.*]], <4 x i8> noundef [[Y:%.*]]) { ; CHECK-NEXT: [[X2:%.*]] = shl nuw nsw <4 x i8> [[X]], ; CHECK-NEXT: [[Y2:%.*]] = add nuw nsw <4 x i8> [[Y]], -; CHECK-NEXT: [[X2_FROZEN:%.*]] = freeze <4 x i8> [[X2]] -; CHECK-NEXT: [[Y2_FROZEN:%.*]] = freeze <4 x i8> [[Y2]] -; CHECK-NEXT: [[DIV:%.*]] = udiv <4 x i8> [[X2_FROZEN]], [[Y2_FROZEN]] -; CHECK-NEXT: [[TMP1:%.*]] = mul <4 x i8> [[DIV]], [[Y2_FROZEN]] -; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub <4 x i8> [[X2_FROZEN]], [[TMP1]] +; CHECK-NEXT: [[DIV:%.*]] = udiv <4 x i8> [[X2]], [[Y2]] +; CHECK-NEXT: [[TMP1:%.*]] = mul <4 x i8> [[DIV]], [[Y2]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub <4 x i8> [[X2]], [[TMP1]] ; CHECK-NEXT: store <4 x i8> [[DIV]], ptr [[P]], align 4 ; CHECK-NEXT: ret <4 x i8> [[REM_DECOMPOSED]] ; @@ -103,11 +95,9 @@ define i32 @explicit_poison_does_not_freeze(ptr %p, i32 noundef %y) { ; CHECK-SAME: ptr [[P:%.*]], i32 noundef [[Y:%.*]]) { ; CHECK-NEXT: [[X:%.*]] = add i32 poison, 1 ; CHECK-NEXT: [[Y2:%.*]] = add nuw nsw i32 [[Y]], 1 -; CHECK-NEXT: [[X_FROZEN:%.*]] = freeze i32 [[X]] -; CHECK-NEXT: [[Y2_FROZEN:%.*]] = freeze i32 [[Y2]] -; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X_FROZEN]], [[Y2_FROZEN]] -; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2_FROZEN]] -; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X_FROZEN]], [[TMP1]] +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[X]], [[Y2]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X]], [[TMP1]] ; CHECK-NEXT: store i32 [[DIV]], ptr [[P]], align 4 ; CHECK-NEXT: ret i32 [[REM_DECOMPOSED]] ; @@ -124,11 +114,9 @@ define i32 @explicit_poison_does_not_freeze_signed(ptr %p, i32 noundef %y) { ; CHECK-SAME: ptr [[P:%.*]], i32 noundef [[Y:%.*]]) { ; CHECK-NEXT: [[X:%.*]] = add i32 poison, 1 ; CHECK-NEXT: [[Y2:%.*]] = add nuw nsw i32 [[Y]], 1 -; CHECK-NEXT: [[X_FROZEN:%.*]] = freeze i32 [[X]] -; CHECK-NEXT: [[Y2_FROZEN:%.*]] = freeze i32 [[Y2]] -; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X_FROZEN]], [[Y2_FROZEN]] -; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2_FROZEN]] -; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X_FROZEN]], [[TMP1]] +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X]], [[Y2]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[Y2]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[X]], [[TMP1]] ; CHECK-NEXT: store i32 [[DIV]], ptr [[P]], align 4 ; CHECK-NEXT: ret i32 [[REM_DECOMPOSED]] ; -- GitLab From e33db249b53fb70dce62db3ebd82d42239bd1d9d Mon Sep 17 00:00:00 2001 From: Mingming Liu Date: Mon, 20 May 2024 08:55:31 -0700 Subject: [PATCH 094/793] Reland "[ThinLTO] Populate declaration import status except for distributed ThinLTO under a default-off new option" (#92718) The original PR is reviewed in https://github.com/llvm/llvm-project/pull/88024, and this PR adds one line (https://github.com/llvm/llvm-project/pull/92718/commits/b9f04d199dec4f3c221d981dcb91e55298d0693f) to fix test Limit to one thread for in-process ThinLTO to test `LLVM_DEBUG` log. - This should fix build bot failure like https://lab.llvm.org/buildbot/#/builders/259/builds/4727 and https://lab.llvm.org/buildbot/#/builders/9/builds/43876 - I could repro the failure and see interleaved log messages by using `-thinlto-threads=all` **Original Commit Message:** The goal is to populate `declaration` import status if a new flag `-import-declaration` is on. * For in-process ThinLTO, the `declaration` status is visible to backend `function-import` pass, so `FunctionImporter::importFunctions` should read the import status and be no-op for declaration summaries. Basically, the postlink pipeline is updated to keep its current behavior (import definitions), but not updated to handle `declaration` summaries. Two use cases ([better call-graph sort](https://discourse.llvm.org/t/rfc-for-better-call-graph-sort-build-a-more-complete-call-graph-by-adding-more-indirect-call-edges/74029#support-cross-module-function-declaration-import-5) or [cross-module auto-init](https://github.com/llvm/llvm-project/pull/87597#discussion_r1556067195)) would use this bit differently. * For distributed ThinLTO, the `declaration` status is not serialized to bitcode. As discussed, https://github.com/llvm/llvm-project/pull/87600 will do this. --- llvm/include/llvm/IR/ModuleSummaryIndex.h | 7 + .../llvm/Transforms/IPO/FunctionImport.h | 15 +- llvm/lib/LTO/LTO.cpp | 32 ++- llvm/lib/LTO/LTOBackend.cpp | 9 +- llvm/lib/Transforms/IPO/FunctionImport.cpp | 270 ++++++++++++++---- llvm/test/ThinLTO/X86/funcimport-stats.ll | 4 +- .../ThinLTO/X86/import_callee_declaration.ll | 181 ++++++++++++ .../Transforms/FunctionImport/funcimport.ll | 5 +- llvm/tools/llvm-link/llvm-link.cpp | 6 +- 9 files changed, 444 insertions(+), 85 deletions(-) create mode 100644 llvm/test/ThinLTO/X86/import_callee_declaration.ll diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h index 5d137d4b3553..a6bb261af752 100644 --- a/llvm/include/llvm/IR/ModuleSummaryIndex.h +++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h @@ -587,6 +587,10 @@ public: void setImportKind(ImportKind IK) { Flags.ImportType = IK; } + GlobalValueSummary::ImportKind importType() const { + return static_cast(Flags.ImportType); + } + GlobalValue::VisibilityTypes getVisibility() const { return (GlobalValue::VisibilityTypes)Flags.Visibility; } @@ -1272,6 +1276,9 @@ using ModulePathStringTableTy = StringMap; /// a particular module, and provide efficient access to their summary. using GVSummaryMapTy = DenseMap; +/// A set of global value summary pointers. +using GVSummaryPtrSet = SmallPtrSet; + /// Map of a type GUID to type id string and summary (multimap used /// in case of GUID conflicts). using TypeIdSummaryMapTy = diff --git a/llvm/include/llvm/Transforms/IPO/FunctionImport.h b/llvm/include/llvm/Transforms/IPO/FunctionImport.h index c4d19e8641ec..024bba8105b8 100644 --- a/llvm/include/llvm/Transforms/IPO/FunctionImport.h +++ b/llvm/include/llvm/Transforms/IPO/FunctionImport.h @@ -31,9 +31,9 @@ class Module; /// based on the provided summary informations. class FunctionImporter { public: - /// Set of functions to import from a source module. Each entry is a set - /// containing all the GUIDs of all functions to import for a source module. - using FunctionsToImportTy = std::unordered_set; + /// The functions to import from a source module and their import type. + using FunctionsToImportTy = + DenseMap; /// The different reasons selectCallee will chose not to import a /// candidate. @@ -99,8 +99,13 @@ public: /// index's module path string table). using ImportMapTy = DenseMap; - /// The set contains an entry for every global value the module exports. - using ExportSetTy = DenseSet; + /// The map contains an entry for every global value the module exports. + /// The key is ValueInfo, and the value indicates whether the definition + /// or declaration is visible to another module. If a function's definition is + /// visible to other modules, the global values this function referenced are + /// visible and shouldn't be internalized. + /// TODO: Rename to `ExportMapTy`. + using ExportSetTy = DenseMap; /// A function of this type is used to load modules referenced by the index. using ModuleLoaderTy = diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index 5c603ac6ab47..e2754d74979e 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -121,6 +121,9 @@ void llvm::computeLTOCacheKey( support::endian::write64le(Data, I); Hasher.update(Data); }; + auto AddUint8 = [&](const uint8_t I) { + Hasher.update(ArrayRef((const uint8_t *)&I, 1)); + }; AddString(Conf.CPU); // FIXME: Hash more of Options. For now all clients initialize Options from // command-line flags (which is unsupported in production), but may set @@ -156,18 +159,18 @@ void llvm::computeLTOCacheKey( auto ModHash = Index.getModuleHash(ModuleID); Hasher.update(ArrayRef((uint8_t *)&ModHash[0], sizeof(ModHash))); - std::vector ExportsGUID; + std::vector> ExportsGUID; ExportsGUID.reserve(ExportList.size()); - for (const auto &VI : ExportList) { - auto GUID = VI.getGUID(); - ExportsGUID.push_back(GUID); - } + for (const auto &[VI, ExportType] : ExportList) + ExportsGUID.push_back( + std::make_pair(VI.getGUID(), static_cast(ExportType))); // Sort the export list elements GUIDs. llvm::sort(ExportsGUID); - for (uint64_t GUID : ExportsGUID) { + for (auto [GUID, ExportType] : ExportsGUID) { // The export list can impact the internalization, be conservative here Hasher.update(ArrayRef((uint8_t *)&GUID, sizeof(GUID))); + AddUint8(ExportType); } // Include the hash for every module we import functions from. The set of @@ -199,7 +202,7 @@ void llvm::computeLTOCacheKey( [](const ImportModule &Lhs, const ImportModule &Rhs) -> bool { return Lhs.getHash() < Rhs.getHash(); }); - std::vector ImportedGUIDs; + std::vector> ImportedGUIDs; for (const ImportModule &Entry : ImportModulesVector) { auto ModHash = Entry.getHash(); Hasher.update(ArrayRef((uint8_t *)&ModHash[0], sizeof(ModHash))); @@ -207,11 +210,13 @@ void llvm::computeLTOCacheKey( AddUint64(Entry.getFunctions().size()); ImportedGUIDs.clear(); - for (auto &Fn : Entry.getFunctions()) - ImportedGUIDs.push_back(Fn); + for (auto &[Fn, ImportType] : Entry.getFunctions()) + ImportedGUIDs.push_back(std::make_pair(Fn, ImportType)); llvm::sort(ImportedGUIDs); - for (auto &GUID : ImportedGUIDs) + for (auto &[GUID, Type] : ImportedGUIDs) { AddUint64(GUID); + AddUint8(Type); + } } // Include the hash for the resolved ODR. @@ -281,9 +286,9 @@ void llvm::computeLTOCacheKey( // Imported functions may introduce new uses of type identifier resolutions, // so we need to collect their used resolutions as well. for (const ImportModule &ImpM : ImportModulesVector) - for (auto &ImpF : ImpM.getFunctions()) { + for (auto &[GUID, UnusedImportType] : ImpM.getFunctions()) { GlobalValueSummary *S = - Index.findSummaryInModule(ImpF, ImpM.getIdentifier()); + Index.findSummaryInModule(GUID, ImpM.getIdentifier()); AddUsedThings(S); // If this is an alias, we also care about any types/etc. that the aliasee // may reference. @@ -1395,6 +1400,7 @@ public: llvm::StringRef ModulePath, const std::string &NewModulePath) { std::map ModuleToSummariesForIndex; + std::error_code EC; gatherImportedSummariesForModule(ModulePath, ModuleToDefinedGVSummaries, ImportList, ModuleToSummariesForIndex); @@ -1403,6 +1409,8 @@ public: sys::fs::OpenFlags::OF_None); if (EC) return errorCodeToError(EC); + + // TODO: Serialize declaration bits to bitcode. writeIndexToFile(CombinedIndex, OS, &ModuleToSummariesForIndex); if (ShouldEmitImportsFiles) { diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp index 21aed799d6fa..76223e88ca1a 100644 --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -720,7 +720,14 @@ bool lto::initImportList(const Module &M, if (Summary->modulePath() == M.getModuleIdentifier()) continue; // Add an entry to provoke importing by thinBackend. - ImportList[Summary->modulePath()].insert(GUID); + // Try emplace the entry first. If an entry with the same key already + // exists, set the value to 'std::min(existing-value, new-value)' to make + // sure a definition takes precedence over a declaration. + auto [Iter, Inserted] = ImportList[Summary->modulePath()].try_emplace( + GUID, Summary->importType()); + + if (!Inserted) + Iter->second = std::min(Iter->second, Summary->importType()); } } return true; diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp index 68f9799616ae..a116fd653534 100644 --- a/llvm/lib/Transforms/IPO/FunctionImport.cpp +++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp @@ -140,6 +140,17 @@ static cl::opt ImportAllIndex("import-all-index", cl::desc("Import all external functions in index.")); +/// This is a test-only option. +/// If this option is enabled, the ThinLTO indexing step will import each +/// function declaration as a fallback. In a real build this may increase ram +/// usage of the indexing step unnecessarily. +/// TODO: Implement selective import (based on combined summary analysis) to +/// ensure the imported function has a use case in the postlink pipeline. +static cl::opt ImportDeclaration( + "import-declaration", cl::init(false), cl::Hidden, + cl::desc("If true, import function declaration as fallback if the function " + "definition is not imported.")); + /// Pass a workload description file - an example of workload would be the /// functions executed to satisfy a RPC request. A workload is defined by a root /// function and the list of functions that are (frequently) needed to satisfy @@ -245,8 +256,12 @@ static auto qualifyCalleeCandidates( } /// Given a list of possible callee implementation for a call site, select one -/// that fits the \p Threshold. If none are found, the Reason will give the last -/// reason for the failure (last, in the order of CalleeSummaryList entries). +/// that fits the \p Threshold for function definition import. If none are +/// found, the Reason will give the last reason for the failure (last, in the +/// order of CalleeSummaryList entries). While looking for a callee definition, +/// sets \p TooLargeOrNoInlineSummary to the last seen too-large or noinline +/// candidate; other modules may want to know the function summary or +/// declaration even if a definition is not needed. /// /// FIXME: select "best" instead of first that fits. But what is "best"? /// - The smallest: more likely to be inlined. @@ -259,24 +274,32 @@ static const GlobalValueSummary * selectCallee(const ModuleSummaryIndex &Index, ArrayRef> CalleeSummaryList, unsigned Threshold, StringRef CallerModulePath, + const GlobalValueSummary *&TooLargeOrNoInlineSummary, FunctionImporter::ImportFailureReason &Reason) { + // Records the last summary with reason noinline or too-large. + TooLargeOrNoInlineSummary = nullptr; auto QualifiedCandidates = qualifyCalleeCandidates(Index, CalleeSummaryList, CallerModulePath); for (auto QualifiedValue : QualifiedCandidates) { Reason = QualifiedValue.first; + // Skip a summary if its import is not (proved to be) legal. if (Reason != FunctionImporter::ImportFailureReason::None) continue; auto *Summary = cast(QualifiedValue.second->getBaseObject()); + // Don't bother importing the definition if the chance of inlining it is + // not high enough (except under `--force-import-all`). if ((Summary->instCount() > Threshold) && !Summary->fflags().AlwaysInline && !ForceImportAll) { + TooLargeOrNoInlineSummary = Summary; Reason = FunctionImporter::ImportFailureReason::TooLarge; continue; } - // Don't bother importing if we can't inline it anyway. + // Don't bother importing the definition if we can't inline it anyway. if (Summary->fflags().NoInline && !ForceImportAll) { + TooLargeOrNoInlineSummary = Summary; Reason = FunctionImporter::ImportFailureReason::NoInline; continue; } @@ -358,17 +381,27 @@ class GlobalsImporter final { if (!GVS || !Index.canImportGlobalVar(GVS, /* AnalyzeRefs */ true) || LocalNotInModule(GVS)) continue; - auto ILI = ImportList[RefSummary->modulePath()].insert(VI.getGUID()); + + // If there isn't an entry for GUID, insert pair. + // Otherwise, definition should take precedence over declaration. + auto [Iter, Inserted] = + ImportList[RefSummary->modulePath()].try_emplace( + VI.getGUID(), GlobalValueSummary::Definition); // Only update stat and exports if we haven't already imported this // variable. - if (!ILI.second) + if (!Inserted) { + // Set the value to 'std::min(existing-value, new-value)' to make + // sure a definition takes precedence over a declaration. + Iter->second = std::min(GlobalValueSummary::Definition, Iter->second); break; + } NumImportedGlobalVarsThinLink++; // Any references made by this variable will be marked exported // later, in ComputeCrossModuleImport, after import decisions are // complete, which is more efficient than adding them here. if (ExportLists) - (*ExportLists)[RefSummary->modulePath()].insert(VI); + (*ExportLists)[RefSummary->modulePath()][VI] = + GlobalValueSummary::Definition; // If variable is not writeonly we attempt to recursively analyze // its references in order to import referenced constants. @@ -545,10 +578,11 @@ class WorkloadImportsManager : public ModuleImportsManager { LLVM_DEBUG(dbgs() << "[Workload][Including]" << VI.name() << " from " << ExportingModule << " : " << Function::getGUID(VI.name()) << "\n"); - ImportList[ExportingModule].insert(VI.getGUID()); + ImportList[ExportingModule][VI.getGUID()] = + GlobalValueSummary::Definition; GVI.onImportingSummary(*GVS); if (ExportLists) - (*ExportLists)[ExportingModule].insert(VI); + (*ExportLists)[ExportingModule][VI] = GlobalValueSummary::Definition; } LLVM_DEBUG(dbgs() << "[Workload] Done\n"); } @@ -769,9 +803,28 @@ static void computeImportForFunction( } FunctionImporter::ImportFailureReason Reason{}; - CalleeSummary = selectCallee(Index, VI.getSummaryList(), NewThreshold, - Summary.modulePath(), Reason); + + // `SummaryForDeclImport` is an summary eligible for declaration import. + const GlobalValueSummary *SummaryForDeclImport = nullptr; + CalleeSummary = + selectCallee(Index, VI.getSummaryList(), NewThreshold, + Summary.modulePath(), SummaryForDeclImport, Reason); if (!CalleeSummary) { + // There isn't a callee for definition import but one for declaration + // import. + if (ImportDeclaration && SummaryForDeclImport) { + StringRef DeclSourceModule = SummaryForDeclImport->modulePath(); + + // Since definition takes precedence over declaration for the same VI, + // try emplace pair without checking insert result. + // If insert doesn't happen, there must be an existing entry keyed by + // VI. + if (ExportLists) + (*ExportLists)[DeclSourceModule].try_emplace( + VI, GlobalValueSummary::Declaration); + ImportList[DeclSourceModule].try_emplace( + VI.getGUID(), GlobalValueSummary::Declaration); + } // Update with new larger threshold if this was a retry (otherwise // we would have already inserted with NewThreshold above). Also // update failure info if requested. @@ -816,11 +869,15 @@ static void computeImportForFunction( "selectCallee() didn't honor the threshold"); auto ExportModulePath = ResolvedCalleeSummary->modulePath(); - auto ILI = ImportList[ExportModulePath].insert(VI.getGUID()); + + // Try emplace the definition entry, and update stats based on insertion + // status. + auto [Iter, Inserted] = ImportList[ExportModulePath].try_emplace( + VI.getGUID(), GlobalValueSummary::Definition); + // We previously decided to import this GUID definition if it was already // inserted in the set of imports from the exporting module. - bool PreviouslyImported = !ILI.second; - if (!PreviouslyImported) { + if (Inserted || Iter->second == GlobalValueSummary::Declaration) { NumImportedFunctionsThinLink++; if (IsHotCallsite) NumImportedHotFunctionsThinLink++; @@ -828,11 +885,14 @@ static void computeImportForFunction( NumImportedCriticalFunctionsThinLink++; } + if (Iter->second == GlobalValueSummary::Declaration) + Iter->second = GlobalValueSummary::Definition; + // Any calls/references made by this function will be marked exported // later, in ComputeCrossModuleImport, after import decisions are // complete, which is more efficient than adding them here. if (ExportLists) - (*ExportLists)[ExportModulePath].insert(VI); + (*ExportLists)[ExportModulePath][VI] = GlobalValueSummary::Definition; } auto GetAdjustedThreshold = [](unsigned Threshold, bool IsHotCallsite) { @@ -939,12 +999,20 @@ static bool isGlobalVarSummary(const ModuleSummaryIndex &Index, } template -static unsigned numGlobalVarSummaries(const ModuleSummaryIndex &Index, - T &Cont) { +static unsigned numGlobalVarSummaries(const ModuleSummaryIndex &Index, T &Cont, + unsigned &DefinedGVS, + unsigned &DefinedFS) { unsigned NumGVS = 0; - for (auto &V : Cont) - if (isGlobalVarSummary(Index, V)) + DefinedGVS = 0; + DefinedFS = 0; + for (auto &[GUID, Type] : Cont) { + if (isGlobalVarSummary(Index, GUID)) { + if (Type == GlobalValueSummary::Definition) + ++DefinedGVS; ++NumGVS; + } else if (Type == GlobalValueSummary::Definition) + ++DefinedFS; + } return NumGVS; } #endif @@ -954,13 +1022,12 @@ static bool checkVariableImport( const ModuleSummaryIndex &Index, DenseMap &ImportLists, DenseMap &ExportLists) { - DenseSet FlattenedImports; for (auto &ImportPerModule : ImportLists) for (auto &ExportPerModule : ImportPerModule.second) - FlattenedImports.insert(ExportPerModule.second.begin(), - ExportPerModule.second.end()); + for (auto &[GUID, Type] : ExportPerModule.second) + FlattenedImports.insert(GUID); // Checks that all GUIDs of read/writeonly vars we see in export lists // are also in the import lists. Otherwise we my face linker undefs, @@ -979,7 +1046,7 @@ static bool checkVariableImport( }; for (auto &ExportPerModule : ExportLists) - for (auto &VI : ExportPerModule.second) + for (auto &[VI, Unused] : ExportPerModule.second) if (!FlattenedImports.count(VI.getGUID()) && IsReadOrWriteOnlyVarNeedingImporting(ExportPerModule.first, VI)) return false; @@ -1015,7 +1082,11 @@ void llvm::ComputeCrossModuleImport( FunctionImporter::ExportSetTy NewExports; const auto &DefinedGVSummaries = ModuleToDefinedGVSummaries.lookup(ELI.first); - for (auto &EI : ELI.second) { + for (auto &[EI, Type] : ELI.second) { + // If a variable is exported as a declaration, its 'refs' and 'calls' are + // not further exported. + if (Type == GlobalValueSummary::Declaration) + continue; // Find the copy defined in the exporting module so that we can mark the // values it references in that specific definition as exported. // Below we will add all references and called values, without regard to @@ -1034,22 +1105,31 @@ void llvm::ComputeCrossModuleImport( // we convert such variables initializers to "zeroinitializer". // See processGlobalForThinLTO. if (!Index.isWriteOnly(GVS)) - for (const auto &VI : GVS->refs()) - NewExports.insert(VI); + for (const auto &VI : GVS->refs()) { + // Try to emplace the declaration entry. If a definition entry + // already exists for key `VI`, this is a no-op. + NewExports.try_emplace(VI, GlobalValueSummary::Declaration); + } } else { auto *FS = cast(S); - for (const auto &Edge : FS->calls()) - NewExports.insert(Edge.first); - for (const auto &Ref : FS->refs()) - NewExports.insert(Ref); + for (const auto &Edge : FS->calls()) { + // Try to emplace the declaration entry. If a definition entry + // already exists for key `VI`, this is a no-op. + NewExports.try_emplace(Edge.first, GlobalValueSummary::Declaration); + } + for (const auto &Ref : FS->refs()) { + // Try to emplace the declaration entry. If a definition entry + // already exists for key `VI`, this is a no-op. + NewExports.try_emplace(Ref, GlobalValueSummary::Declaration); + } } } - // Prune list computed above to only include values defined in the exporting - // module. We do this after the above insertion since we may hit the same - // ref/call target multiple times in above loop, and it is more efficient to - // avoid a set lookup each time. + // Prune list computed above to only include values defined in the + // exporting module. We do this after the above insertion since we may hit + // the same ref/call target multiple times in above loop, and it is more + // efficient to avoid a set lookup each time. for (auto EI = NewExports.begin(); EI != NewExports.end();) { - if (!DefinedGVSummaries.count(EI->getGUID())) + if (!DefinedGVSummaries.count(EI->first.getGUID())) NewExports.erase(EI++); else ++EI; @@ -1064,18 +1144,29 @@ void llvm::ComputeCrossModuleImport( for (auto &ModuleImports : ImportLists) { auto ModName = ModuleImports.first; auto &Exports = ExportLists[ModName]; - unsigned NumGVS = numGlobalVarSummaries(Index, Exports); - LLVM_DEBUG(dbgs() << "* Module " << ModName << " exports " - << Exports.size() - NumGVS << " functions and " << NumGVS - << " vars. Imports from " << ModuleImports.second.size() - << " modules.\n"); + unsigned DefinedGVS = 0, DefinedFS = 0; + unsigned NumGVS = + numGlobalVarSummaries(Index, Exports, DefinedGVS, DefinedFS); + LLVM_DEBUG(dbgs() << "* Module " << ModName << " exports " << DefinedFS + << " function as definitions, " + << Exports.size() - NumGVS - DefinedFS + << " functions as declarations, " << DefinedGVS + << " var definitions and " << NumGVS - DefinedGVS + << " var declarations. Imports from " + << ModuleImports.second.size() << " modules.\n"); for (auto &Src : ModuleImports.second) { auto SrcModName = Src.first; - unsigned NumGVSPerMod = numGlobalVarSummaries(Index, Src.second); - LLVM_DEBUG(dbgs() << " - " << Src.second.size() - NumGVSPerMod - << " functions imported from " << SrcModName << "\n"); - LLVM_DEBUG(dbgs() << " - " << NumGVSPerMod - << " global vars imported from " << SrcModName << "\n"); + unsigned DefinedGVS = 0, DefinedFS = 0; + unsigned NumGVSPerMod = + numGlobalVarSummaries(Index, Src.second, DefinedGVS, DefinedFS); + LLVM_DEBUG(dbgs() << " - " << DefinedFS << " function definitions and " + << Src.second.size() - NumGVSPerMod - DefinedFS + << " function declarations imported from " << SrcModName + << "\n"); + LLVM_DEBUG(dbgs() << " - " << DefinedGVS << " global vars definition and " + << NumGVSPerMod - DefinedGVS + << " global vars declaration imported from " + << SrcModName << "\n"); } } #endif @@ -1089,11 +1180,17 @@ static void dumpImportListForModule(const ModuleSummaryIndex &Index, << ImportList.size() << " modules.\n"); for (auto &Src : ImportList) { auto SrcModName = Src.first; - unsigned NumGVSPerMod = numGlobalVarSummaries(Index, Src.second); - LLVM_DEBUG(dbgs() << " - " << Src.second.size() - NumGVSPerMod - << " functions imported from " << SrcModName << "\n"); - LLVM_DEBUG(dbgs() << " - " << NumGVSPerMod << " vars imported from " - << SrcModName << "\n"); + unsigned DefinedGVS = 0, DefinedFS = 0; + unsigned NumGVSPerMod = + numGlobalVarSummaries(Index, Src.second, DefinedGVS, DefinedFS); + LLVM_DEBUG(dbgs() << " - " << DefinedFS << " function definitions and " + << Src.second.size() - DefinedFS - NumGVSPerMod + << " function declarations imported from " << SrcModName + << "\n"); + LLVM_DEBUG(dbgs() << " - " << DefinedGVS << " var definitions and " + << NumGVSPerMod - DefinedGVS + << " var declarations imported from " << SrcModName + << "\n"); } } #endif @@ -1149,7 +1246,13 @@ static void ComputeCrossModuleImportForModuleFromIndexForTest( if (Summary->modulePath() == ModulePath) continue; // Add an entry to provoke importing by thinBackend. - ImportList[Summary->modulePath()].insert(GUID); + auto [Iter, Inserted] = ImportList[Summary->modulePath()].try_emplace( + GUID, Summary->importType()); + if (!Inserted) { + // Use 'std::min' to make sure definition (with enum value 0) takes + // precedence over declaration (with enum value 1). + Iter->second = std::min(Iter->second, Summary->importType()); + } } #ifndef NDEBUG dumpImportListForModule(Index, ModulePath, ImportList); @@ -1339,13 +1442,17 @@ void llvm::gatherImportedSummariesForModule( // Include summaries for imports. for (const auto &ILI : ImportList) { auto &SummariesForIndex = ModuleToSummariesForIndex[std::string(ILI.first)]; + const auto &DefinedGVSummaries = ModuleToDefinedGVSummaries.lookup(ILI.first); - for (const auto &GI : ILI.second) { - const auto &DS = DefinedGVSummaries.find(GI); + for (const auto &[GUID, Type] : ILI.second) { + const auto &DS = DefinedGVSummaries.find(GUID); assert(DS != DefinedGVSummaries.end() && "Expected a defined summary for imported global value"); - SummariesForIndex[GI] = DS->second; + if (Type == GlobalValueSummary::Declaration) + continue; + + SummariesForIndex[GUID] = DS->second; } } } @@ -1617,6 +1724,16 @@ Expected FunctionImporter::importFunctions( for (const auto &FunctionsToImportPerModule : ImportList) { ModuleNameOrderedList.insert(FunctionsToImportPerModule.first); } + + auto getImportType = [&](const FunctionsToImportTy &GUIDToImportType, + GlobalValue::GUID GUID) + -> std::optional { + auto Iter = GUIDToImportType.find(GUID); + if (Iter == GUIDToImportType.end()) + return std::nullopt; + return Iter->second; + }; + for (const auto &Name : ModuleNameOrderedList) { // Get the module for the import const auto &FunctionsToImportPerModule = ImportList.find(Name); @@ -1634,17 +1751,27 @@ Expected FunctionImporter::importFunctions( return std::move(Err); auto &ImportGUIDs = FunctionsToImportPerModule->second; + // Find the globals to import SetVector GlobalsToImport; for (Function &F : *SrcModule) { if (!F.hasName()) continue; auto GUID = F.getGUID(); - auto Import = ImportGUIDs.count(GUID); - LLVM_DEBUG(dbgs() << (Import ? "Is" : "Not") << " importing function " + auto MaybeImportType = getImportType(ImportGUIDs, GUID); + + bool ImportDefinition = + (MaybeImportType && + (*MaybeImportType == GlobalValueSummary::Definition)); + + LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not") + << " importing function" + << (ImportDefinition + ? " definition " + : (MaybeImportType ? " declaration " : " ")) << GUID << " " << F.getName() << " from " << SrcModule->getSourceFileName() << "\n"); - if (Import) { + if (ImportDefinition) { if (Error Err = F.materialize()) return std::move(Err); // MemProf should match function's definition and summary, @@ -1670,11 +1797,20 @@ Expected FunctionImporter::importFunctions( if (!GV.hasName()) continue; auto GUID = GV.getGUID(); - auto Import = ImportGUIDs.count(GUID); - LLVM_DEBUG(dbgs() << (Import ? "Is" : "Not") << " importing global " + auto MaybeImportType = getImportType(ImportGUIDs, GUID); + + bool ImportDefinition = + (MaybeImportType && + (*MaybeImportType == GlobalValueSummary::Definition)); + + LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not") + << " importing global" + << (ImportDefinition + ? " definition " + : (MaybeImportType ? " declaration " : " ")) << GUID << " " << GV.getName() << " from " << SrcModule->getSourceFileName() << "\n"); - if (Import) { + if (ImportDefinition) { if (Error Err = GV.materialize()) return std::move(Err); ImportedGVCount += GlobalsToImport.insert(&GV); @@ -1684,11 +1820,20 @@ Expected FunctionImporter::importFunctions( if (!GA.hasName() || isa(GA.getAliaseeObject())) continue; auto GUID = GA.getGUID(); - auto Import = ImportGUIDs.count(GUID); - LLVM_DEBUG(dbgs() << (Import ? "Is" : "Not") << " importing alias " + auto MaybeImportType = getImportType(ImportGUIDs, GUID); + + bool ImportDefinition = + (MaybeImportType && + (*MaybeImportType == GlobalValueSummary::Definition)); + + LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not") + << " importing alias" + << (ImportDefinition + ? " definition " + : (MaybeImportType ? " declaration " : " ")) << GUID << " " << GA.getName() << " from " << SrcModule->getSourceFileName() << "\n"); - if (Import) { + if (ImportDefinition) { if (Error Err = GA.materialize()) return std::move(Err); // Import alias as a copy of its aliasee. @@ -1754,6 +1899,7 @@ Expected FunctionImporter::importFunctions( NumImportedFunctions += (ImportedCount - ImportedGVCount); NumImportedGlobalVars += ImportedGVCount; + // TODO: Print counters for definitions and declarations in the debugging log. LLVM_DEBUG(dbgs() << "Imported " << ImportedCount - ImportedGVCount << " functions for Module " << DestModule.getModuleIdentifier() << "\n"); diff --git a/llvm/test/ThinLTO/X86/funcimport-stats.ll b/llvm/test/ThinLTO/X86/funcimport-stats.ll index 913b13004c1c..7fcd33855fe1 100644 --- a/llvm/test/ThinLTO/X86/funcimport-stats.ll +++ b/llvm/test/ThinLTO/X86/funcimport-stats.ll @@ -9,8 +9,8 @@ ; RUN: cat %t4 | grep 'Is importing aliasee' | count 1 ; RUN: cat %t4 | FileCheck %s -; CHECK: - [[NUM_FUNCS:[0-9]+]] functions imported from -; CHECK-NEXT: - [[NUM_VARS:[0-9]+]] global vars imported from +; CHECK: - [[NUM_FUNCS:[0-9]+]] function definitions and 0 function declarations imported from +; CHECK-NEXT: - [[NUM_VARS:[0-9]+]] global vars definition and 0 global vars declaration imported from ; CHECK: [[NUM_FUNCS]] function-import - Number of functions imported in backend ; CHECK-NEXT: [[NUM_FUNCS]] function-import - Number of functions thin link decided to import diff --git a/llvm/test/ThinLTO/X86/import_callee_declaration.ll b/llvm/test/ThinLTO/X86/import_callee_declaration.ll new file mode 100644 index 000000000000..43214e3cf941 --- /dev/null +++ b/llvm/test/ThinLTO/X86/import_callee_declaration.ll @@ -0,0 +1,181 @@ +; "-debug-only" requires asserts. +; REQUIRES: asserts +; RUN: rm -rf %t && split-file %s %t && cd %t + +; Generate per-module summaries. +; RUN: opt -module-summary main.ll -o main.bc +; RUN: opt -module-summary lib.ll -o lib.bc + +; Generate the combined summary and distributed indices. + +; - For function import, set 'import-instr-limit' to 7 and fall back to import +; function declarations. +; - In main.ll, function 'main' calls 'small_func' and 'large_func'. Both callees +; are defined in lib.ll. 'small_func' has two indirect callees, one is smaller +; and the other one is larger. Both callees of 'small_func' are defined in lib.ll. +; - Given the import limit, in main's combined summary, the import type of 'small_func' +; and 'small_indirect_callee' will be 'definition', and the import type of +; 'large_func' and 'large_indirect_callee' will be 'declaration'. +; +; The test will disassemble combined summaries and check the import type is +; correct. Right now postlink optimizer pipeline doesn't do anything (e.g., +; import the declaration or de-serialize summary attributes yet) so there is +; nothing to test more than the summary content. +; +; RUN: llvm-lto2 run \ +; RUN: -debug-only=function-import \ +; RUN: -import-instr-limit=7 \ +; RUN: -import-declaration \ +; RUN: -thinlto-distributed-indexes \ +; RUN: -r=main.bc,main,px \ +; RUN: -r=main.bc,small_func, \ +; RUN: -r=main.bc,large_func, \ +; RUN: -r=lib.bc,callee,pl \ +; RUN: -r=lib.bc,large_indirect_callee,px \ +; RUN: -r=lib.bc,small_func,px \ +; RUN: -r=lib.bc,large_func,px \ +; RUN: -r=lib.bc,large_indirect_callee_alias,px \ +; RUN: -r=lib.bc,calleeAddrs,px -o summary main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=DUMP +; +; RUN: llvm-lto -thinlto-action=thinlink -import-declaration -import-instr-limit=7 -o combined.index.bc main.bc lib.bc +; RUN: llvm-lto -thinlto-action=distributedindexes -debug-only=function-import -import-declaration -import-instr-limit=7 -thinlto-index combined.index.bc main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=DUMP + +; DUMP: - 2 function definitions and 3 function declarations imported from lib.bc + +; First disassemble per-module summary and find out the GUID for {large_func, large_indirect_callee}. +; +; RUN: llvm-dis lib.bc -o - | FileCheck %s --check-prefix=LIB-DIS +; LIB-DIS: [[LARGEFUNC:\^[0-9]+]] = gv: (name: "large_func", summaries: {{.*}}) ; guid = 2418497564662708935 +; LIB-DIS: [[LARGEINDIRECT:\^[0-9]+]] = gv: (name: "large_indirect_callee", summaries: {{.*}}) ; guid = 14343440786664691134 +; LIB-DIS: [[LARGEINDIRECTALIAS:\^[0-9]+]] = gv: (name: "large_indirect_callee_alias", summaries: {{.*}}, aliasee: [[LARGEINDIRECT]] +; +; Secondly disassemble main's combined summary and test that large callees are +; not imported as declarations yet. +; +; RUN: llvm-dis main.bc.thinlto.bc -o - | FileCheck %s --check-prefix=MAIN-DIS +; +; MAIN-DIS: [[LIBMOD:\^[0-9]+]] = module: (path: "lib.bc", hash: (0, 0, 0, 0, 0)) +; MAIN-DIS-NOT: [[LARGEFUNC:\^[0-9]+]] = gv: (guid: 2418497564662708935, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}}))) +; MAIN-DIS-NOT: [[LARGEINDIRECT:\^[0-9]+]] = gv: (guid: 14343440786664691134, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}}))) +; MAIN-DIS-NOT: [[LARGEINDIRECTALIAS:\^[0-9]+]] = gv: (guid: 16730173943625350469, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration) + +; Run in-process ThinLTO and tests that +; 1. `callee` remains internalized even if the symbols of its callers +; (large_func and large_indirect_callee) are exported as declarations and visible to main module. +; 2. the debugging logs from `function-import` pass are expected. + +; RUN: llvm-lto2 run \ +; RUN: -debug-only=function-import \ +; RUN: -save-temps \ +; RUN: -thinlto-threads=1 \ +; RUN: -import-instr-limit=7 \ +; RUN: -import-declaration \ +; RUN: -r=main.bc,main,px \ +; RUN: -r=main.bc,small_func, \ +; RUN: -r=main.bc,large_func, \ +; RUN: -r=lib.bc,callee,pl \ +; RUN: -r=lib.bc,large_indirect_callee,px \ +; RUN: -r=lib.bc,small_func,px \ +; RUN: -r=lib.bc,large_func,px \ +; RUN: -r=lib.bc,large_indirect_callee_alias,px \ +; RUN: -r=lib.bc,calleeAddrs,px -o in-process main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=IMPORTDUMP + +; Test import status from debugging logs. +; TODO: Serialize declaration bit and test declaration bits are correctly set, +; and extend this test case to test IR once postlink optimizer makes use of +; the import type for declarations. +; IMPORTDUMP-DAG: Not importing function 11825436545918268459 callee from lib.cc +; IMPORTDUMP-DAG: Is importing function declaration 14343440786664691134 large_indirect_callee from lib.cc +; IMPORTDUMP-DAG: Is importing function definition 13568239288960714650 small_indirect_callee from lib.cc +; IMPORTDUMP-DAG: Is importing function definition 6976996067367342685 small_func from lib.cc +; IMPORTDUMP-DAG: Is importing function declaration 2418497564662708935 large_func from lib.cc +; IMPORTDUMP-DAG: Not importing global 7680325410415171624 calleeAddrs from lib.cc +; IMPORTDUMP-DAG: Is importing alias declaration 16730173943625350469 large_indirect_callee_alias from lib.cc + +; RUN: llvm-dis in-process.1.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT + +; RUN: llvm-dis in-process.2.2.internalize.bc -o - | FileCheck %s --check-prefix=INTERNALIZE + +; IMPORT-DAG: define available_externally void @small_func +; IMPORT-DAG: define available_externally hidden void @small_indirect_callee +; IMPORT-DAG: declare void @large_func +; IMPORT-NOT: large_indirect_callee +; IMPORT-NOT: large_indirect_callee_alias + +; INTERNALIZE: define internal void @callee() + +;--- main.ll +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @main() { + call void @small_func() + call void @large_func() + ret i32 0 +} + +declare void @small_func() + +; large_func without attributes +declare void @large_func() + +;--- lib.ll +source_filename = "lib.cc" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@calleeAddrs = global [3 x ptr] [ptr @large_indirect_callee, ptr @small_indirect_callee, ptr @large_indirect_callee_alias] + +define void @callee() #1 { + ret void +} + +define void @large_indirect_callee()#2 { + call void @callee() + call void @callee() + call void @callee() + call void @callee() + call void @callee() + call void @callee() + call void @callee() + ret void +} + +define internal void @small_indirect_callee() #0 { + ret void +} + +@large_indirect_callee_alias = alias void(), ptr @large_indirect_callee + +define void @small_func() { +entry: + %0 = load ptr, ptr @calleeAddrs + call void %0(), !prof !0 + %1 = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @calleeAddrs, i64 0, i64 1) + call void %1(), !prof !1 + %2 = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @calleeAddrs, i64 0, i64 2) + call void %2(), !prof !2 + ret void +} + +define void @large_func() #0 { +entry: + call void @callee() + call void @callee() + call void @callee() + call void @callee() + call void @callee() + call void @callee() + call void @callee() + ret void +} + +attributes #0 = { nounwind norecurse } + +attributes #1 = { noinline } + +attributes #2 = { norecurse } + +!0 = !{!"VP", i32 0, i64 1, i64 14343440786664691134, i64 1} +!1 = !{!"VP", i32 0, i64 1, i64 13568239288960714650, i64 1} +!2 = !{!"VP", i32 0, i64 1, i64 16730173943625350469, i64 1} diff --git a/llvm/test/Transforms/FunctionImport/funcimport.ll b/llvm/test/Transforms/FunctionImport/funcimport.ll index a0968a67f5ce..635750b33fff 100644 --- a/llvm/test/Transforms/FunctionImport/funcimport.ll +++ b/llvm/test/Transforms/FunctionImport/funcimport.ll @@ -166,7 +166,8 @@ declare void @variadic_va_start(...) ; GUID-DAG: GUID {{.*}} is linkoncefunc ; DUMP: Module [[M1:.*]] imports from 1 module -; DUMP-NEXT: 15 functions imported from [[M2:.*]] -; DUMP-NEXT: 4 vars imported from [[M2]] +; DUMP-NEXT: 15 function definitions and 0 function declarations imported from [[M2:.*]] +; DUMP-NEXT: 4 var definitions and 0 var declarations imported from [[M2]] + ; DUMP: Imported 15 functions for Module [[M1]] ; DUMP-NEXT: Imported 4 global variables for Module [[M1]] diff --git a/llvm/tools/llvm-link/llvm-link.cpp b/llvm/tools/llvm-link/llvm-link.cpp index 7794f2d81ed0..1b90fce76fbd 100644 --- a/llvm/tools/llvm-link/llvm-link.cpp +++ b/llvm/tools/llvm-link/llvm-link.cpp @@ -377,9 +377,13 @@ static bool importFunctions(const char *argv0, Module &DestModule) { if (Verbose) errs() << "Importing " << FunctionName << " from " << FileName << "\n"; + // `-import` specifies the `` pairs to import as + // definition, so make the import type definition directly. + // FIXME: A follow-up patch should add test coverage for import declaration + // in `llvm-link` CLI (e.g., by introducing a new command line option). auto &Entry = ImportList[FileNameStringCache.insert(FileName).first->getKey()]; - Entry.insert(F->getGUID()); + Entry[F->getGUID()] = GlobalValueSummary::Definition; } auto CachedModuleLoader = [&](StringRef Identifier) { return ModuleLoaderCache.takeModule(std::string(Identifier)); -- GitLab From 3efaf9caa56393597839b796d34f92459c711605 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 20 May 2024 12:04:07 -0400 Subject: [PATCH 095/793] [Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (#92452) Clang crashes when diagnosing the following invalid redeclaration in C++11: ``` struct A { void f(); }; constexpr void A::f() { } // crash here ``` This happens because `DiagnoseInvalidRedeclaration` tries to create a fix-it to remove `const` from the out-of-line declaration of `f`, but there is no `SourceLocation` for the `const` qualifier (it's implicitly `const` due to `constexpr`) and an assert in `FunctionTypeInfo::getConstQualifierLoc` fails. This patch changes `DiagnoseInvalidRedeclaration` to only suggest the removal of the `const` qualifier when it was explicitly specified in the _cv-qualifier-seq_ of the declaration. --- clang/docs/ReleaseNotes.rst | 2 ++ clang/lib/Sema/SemaDecl.cpp | 21 ++++++++++--------- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 11 ++++++++++ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 5a123b0b86dd..a89e10524aa1 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -742,6 +742,8 @@ Bug Fixes to C++ Support - Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). - Fix a bug where the last argument was not considered when considering the most viable function for explicit object argument member functions. Fixes (#GH92188). +- Fix a C++11 crash when a non-const non-static member function is defined out-of-line with + the ``constexpr`` specifier. Fixes (#GH61004). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 557fe10619c3..6764a979168d 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9217,19 +9217,20 @@ static NamedDecl *DiagnoseInvalidRedeclaration( << Idx << FDParam->getType() << NewFD->getParamDecl(Idx - 1)->getType(); } else if (FDisConst != NewFDisConst) { - SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) - << NewFDisConst << FD->getSourceRange().getEnd() - << (NewFDisConst - ? FixItHint::CreateRemoval(ExtraArgs.D.getFunctionTypeInfo() - .getConstQualifierLoc()) - : FixItHint::CreateInsertion(ExtraArgs.D.getFunctionTypeInfo() - .getRParenLoc() - .getLocWithOffset(1), - " const")); - } else + auto DB = SemaRef.Diag(FD->getLocation(), + diag::note_member_def_close_const_match) + << NewFDisConst << FD->getSourceRange().getEnd(); + if (const auto &FTI = ExtraArgs.D.getFunctionTypeInfo(); !NewFDisConst) + DB << FixItHint::CreateInsertion(FTI.getRParenLoc().getLocWithOffset(1), + " const"); + else if (FTI.hasMethodTypeQualifiers() && + FTI.getConstQualifierLoc().isValid()) + DB << FixItHint::CreateRemoval(FTI.getConstQualifierLoc()); + } else { SemaRef.Diag(FD->getLocation(), IsMember ? diag::note_member_def_close_match : diag::note_local_decl_close_match); + } } return nullptr; } diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index a28a5f91c477..788e93b56bb3 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -154,3 +154,14 @@ namespace { // FIXME: We should diagnose this prior to C++17. const int &r = A::n; } + +#if __cplusplus < 201402L +namespace ImplicitConstexprDef { + struct A { + void f(); // expected-note {{member declaration does not match because it is not const qualified}} + }; + + constexpr void A::f() { } // expected-warning {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const' to avoid a change in behavior}} + // expected-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'ImplicitConstexprDef::A'}} +} +#endif -- GitLab From 2a2b27d99e3faf34a593c1ed8029ed4744f1cd5d Mon Sep 17 00:00:00 2001 From: David Truby Date: Mon, 20 May 2024 17:16:23 +0100 Subject: [PATCH 096/793] [flang] Fix CMake dependency in CUF/Attributes (#92751) flang/lib/Optimizer/Dialect/CUF/Attributes/CUFAttr.cpp includes CUFDialect.h.inc, but the target generating that isn't currently depended on in CUF/Attributes. This patch adds that missing dependency. Fixes #92635 --- flang/lib/Optimizer/Dialect/CUF/Attributes/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/flang/lib/Optimizer/Dialect/CUF/Attributes/CMakeLists.txt b/flang/lib/Optimizer/Dialect/CUF/Attributes/CMakeLists.txt index 81db40f3ba46..ec5484c1d610 100644 --- a/flang/lib/Optimizer/Dialect/CUF/Attributes/CMakeLists.txt +++ b/flang/lib/Optimizer/Dialect/CUF/Attributes/CMakeLists.txt @@ -5,6 +5,7 @@ add_flang_library(CUFAttrs DEPENDS MLIRIR CUFAttrsIncGen + CUFOpsIncGen LINK_LIBS MLIRTargetLLVMIRExport -- GitLab From 9def85f99aba66fb5a266d2abf60c3802ff13c6a Mon Sep 17 00:00:00 2001 From: inglorion Date: Mon, 20 May 2024 09:35:08 -0700 Subject: [PATCH 097/793] [revert_checker] replace Phabricator URIs with GitHub URIs (#92102) LLVM is now using GitHub. This change makes revert_checker.py -u generate commit links that go to GitHub, instead of the old Phabricator URIs. --- llvm/utils/revert_checker.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/llvm/utils/revert_checker.py b/llvm/utils/revert_checker.py index 34395a6fe505..da80bdff8685 100755 --- a/llvm/utils/revert_checker.py +++ b/llvm/utils/revert_checker.py @@ -283,17 +283,12 @@ def _main() -> None: seen_reverts.add(revert) all_reverts.append(revert) + sha_prefix = ( + "https://github.com/llvm/llvm-project/commit/" if opts.review_url else "" + ) for revert in all_reverts: - sha_fmt = ( - f"https://reviews.llvm.org/rG{revert.sha}" - if opts.review_url - else revert.sha - ) - reverted_sha_fmt = ( - f"https://reviews.llvm.org/rG{revert.reverted_sha}" - if opts.review_url - else revert.reverted_sha - ) + sha_fmt = f"{sha_prefix}{revert.sha}" + reverted_sha_fmt = f"{sha_prefix}{revert.reverted_sha}" print(f"{sha_fmt} claims to revert {reverted_sha_fmt}") -- GitLab From 586ecd75606e70a8d16cb1717809acce652ffe7f Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 20 May 2024 18:36:17 +0200 Subject: [PATCH 098/793] AMDGPU: Relax vector restriction for rootn libcall folds (#92594) We could try harder for nonsplat vectors but probably not worth the effort. --- llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp | 10 +- .../AMDGPU/amdgpu-simplify-libcall-rootn.ll | 111 ++++++++---------- 2 files changed, 54 insertions(+), 67 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp b/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp index faf04c3c7e70..0a5fbf5034c0 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp @@ -1156,17 +1156,13 @@ bool AMDGPULibCalls::fold_pow(FPMathOperator *FPOp, IRBuilder<> &B, bool AMDGPULibCalls::fold_rootn(FPMathOperator *FPOp, IRBuilder<> &B, const FuncInfo &FInfo) { - // skip vector function - if (getVecSize(FInfo) != 1) - return false; - Value *opr0 = FPOp->getOperand(0); Value *opr1 = FPOp->getOperand(1); - ConstantInt *CINT = dyn_cast(opr1); - if (!CINT) { + const APInt *CINT = nullptr; + if (!match(opr1, m_APIntAllowPoison(CINT))) return false; - } + int ci_opr1 = (int)CINT->getSExtValue(); if (ci_opr1 == 1) { // rootn(x, 1) = x LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << *opr0 << "\n"); diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll index 2e64a3456c24..f79983e2491a 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll @@ -342,8 +342,7 @@ define <2 x half> @test_rootn_v2f16_0(<2 x half> %x) { define <2 x half> @test_rootn_v2f16_1(<2 x half> %x) { ; CHECK-LABEL: define <2 x half> @test_rootn_v2f16_1( ; CHECK-SAME: <2 x half> [[X:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> [[X]], <2 x i32> ) -; CHECK-NEXT: ret <2 x half> [[CALL]] +; CHECK-NEXT: ret <2 x half> [[X]] ; %call = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> %x, <2 x i32> ) ret <2 x half> %call @@ -352,8 +351,8 @@ define <2 x half> @test_rootn_v2f16_1(<2 x half> %x) { define <2 x half> @test_rootn_v2f16_2(<2 x half> %x) { ; CHECK-LABEL: define <2 x half> @test_rootn_v2f16_2( ; CHECK-SAME: <2 x half> [[X:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> [[X]], <2 x i32> ) -; CHECK-NEXT: ret <2 x half> [[CALL]] +; CHECK-NEXT: [[__ROOTN2SQRT:%.*]] = call <2 x half> @_Z4sqrtDv2_Dh(<2 x half> [[X]]) +; CHECK-NEXT: ret <2 x half> [[__ROOTN2SQRT]] ; %call = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> %x, <2 x i32> ) ret <2 x half> %call @@ -362,8 +361,8 @@ define <2 x half> @test_rootn_v2f16_2(<2 x half> %x) { define <2 x half> @test_rootn_v2f16_neg1(<2 x half> %x) { ; CHECK-LABEL: define <2 x half> @test_rootn_v2f16_neg1( ; CHECK-SAME: <2 x half> [[X:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> [[X]], <2 x i32> ) -; CHECK-NEXT: ret <2 x half> [[CALL]] +; CHECK-NEXT: [[__ROOTN2DIV:%.*]] = fdiv <2 x half> , [[X]] +; CHECK-NEXT: ret <2 x half> [[__ROOTN2DIV]] ; %call = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> %x, <2 x i32> ) ret <2 x half> %call @@ -372,8 +371,8 @@ define <2 x half> @test_rootn_v2f16_neg1(<2 x half> %x) { define <2 x half> @test_rootn_v2f16_neg2(<2 x half> %x) { ; CHECK-LABEL: define <2 x half> @test_rootn_v2f16_neg2( ; CHECK-SAME: <2 x half> [[X:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> [[X]], <2 x i32> ) -; CHECK-NEXT: ret <2 x half> [[CALL]] +; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call <2 x half> @_Z5rsqrtDv2_Dh(<2 x half> [[X]]) +; CHECK-NEXT: ret <2 x half> [[__ROOTN2RSQRT]] ; %call = tail call <2 x half> @_Z5rootnDv2_DhDv2_i(<2 x half> %x, <2 x i32> ) ret <2 x half> %call @@ -523,8 +522,7 @@ define <2 x float> @test_rootn_v2f32__y_1(<2 x float> %x) { ; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_1( ; CHECK-SAME: <2 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> ) -; CHECK-NEXT: ret <2 x float> [[CALL]] +; CHECK-NEXT: ret <2 x float> [[X]] ; entry: %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> ) @@ -535,8 +533,7 @@ define <2 x float> @test_rootn_v2f32__y_1__strictfp(<2 x float> %x) #1 { ; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_1__strictfp( ; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> ) #[[ATTR0]] -; CHECK-NEXT: ret <2 x float> [[CALL]] +; CHECK-NEXT: ret <2 x float> [[X]] ; entry: %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> ) #1 @@ -547,8 +544,7 @@ define <2 x float> @test_rootn_v2f32__y_1_undef(<2 x float> %x) { ; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_1_undef( ; CHECK-SAME: <2 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> ) -; CHECK-NEXT: ret <2 x float> [[CALL]] +; CHECK-NEXT: ret <2 x float> [[X]] ; entry: %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> ) @@ -559,8 +555,7 @@ define <3 x float> @test_rootn_v3f32__y_1(<3 x float> %x) { ; CHECK-LABEL: define <3 x float> @test_rootn_v3f32__y_1( ; CHECK-SAME: <3 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> [[X]], <3 x i32> ) -; CHECK-NEXT: ret <3 x float> [[CALL]] +; CHECK-NEXT: ret <3 x float> [[X]] ; entry: %call = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> %x, <3 x i32> ) @@ -571,8 +566,7 @@ define <3 x float> @test_rootn_v3f32__y_1_undef(<3 x float> %x) { ; CHECK-LABEL: define <3 x float> @test_rootn_v3f32__y_1_undef( ; CHECK-SAME: <3 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> [[X]], <3 x i32> ) -; CHECK-NEXT: ret <3 x float> [[CALL]] +; CHECK-NEXT: ret <3 x float> [[X]] ; entry: %call = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> %x, <3 x i32> ) @@ -583,8 +577,7 @@ define <4 x float> @test_rootn_v4f32__y_1(<4 x float> %x) { ; CHECK-LABEL: define <4 x float> @test_rootn_v4f32__y_1( ; CHECK-SAME: <4 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <4 x float> @_Z5rootnDv4_fDv4_i(<4 x float> [[X]], <4 x i32> ) -; CHECK-NEXT: ret <4 x float> [[CALL]] +; CHECK-NEXT: ret <4 x float> [[X]] ; entry: %call = tail call <4 x float> @_Z5rootnDv4_fDv4_i(<4 x float> %x, <4 x i32> ) @@ -595,8 +588,7 @@ define <8 x float> @test_rootn_v8f32__y_1(<8 x float> %x) { ; CHECK-LABEL: define <8 x float> @test_rootn_v8f32__y_1( ; CHECK-SAME: <8 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <8 x float> @_Z5rootnDv8_fDv8_i(<8 x float> [[X]], <8 x i32> ) -; CHECK-NEXT: ret <8 x float> [[CALL]] +; CHECK-NEXT: ret <8 x float> [[X]] ; entry: %call = tail call <8 x float> @_Z5rootnDv8_fDv8_i(<8 x float> %x, <8 x i32> ) @@ -607,8 +599,7 @@ define <16 x float> @test_rootn_v16f32__y_1(<16 x float> %x) { ; CHECK-LABEL: define <16 x float> @test_rootn_v16f32__y_1( ; CHECK-SAME: <16 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <16 x float> @_Z5rootnDv16_fDv16_i(<16 x float> [[X]], <16 x i32> ) -; CHECK-NEXT: ret <16 x float> [[CALL]] +; CHECK-NEXT: ret <16 x float> [[X]] ; entry: %call = tail call <16 x float> @_Z5rootnDv16_fDv16_i(<16 x float> %x, <16 x i32> ) @@ -656,8 +647,8 @@ define <2 x float> @test_rootn_v2f32__y_2_flags(<2 x float> %x) { ; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_2_flags( ; CHECK-SAME: <2 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call nnan nsz <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> ) -; CHECK-NEXT: ret <2 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2SQRT:%.*]] = call nnan nsz <2 x float> @_Z4sqrtDv2_f(<2 x float> [[X]]) +; CHECK-NEXT: ret <2 x float> [[__ROOTN2SQRT]] ; entry: %call = tail call nnan nsz <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> ) @@ -668,8 +659,8 @@ define <3 x float> @test_rootn_v3f32__y_2(<3 x float> %x) { ; CHECK-LABEL: define <3 x float> @test_rootn_v3f32__y_2( ; CHECK-SAME: <3 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> [[X]], <3 x i32> ) -; CHECK-NEXT: ret <3 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2SQRT:%.*]] = call <3 x float> @_Z4sqrtDv3_f(<3 x float> [[X]]) +; CHECK-NEXT: ret <3 x float> [[__ROOTN2SQRT]] ; entry: %call = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> %x, <3 x i32> ) @@ -680,8 +671,8 @@ define <3 x float> @test_rootn_v3f32__y_2_undef(<3 x float> %x) { ; CHECK-LABEL: define <3 x float> @test_rootn_v3f32__y_2_undef( ; CHECK-SAME: <3 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> [[X]], <3 x i32> ) -; CHECK-NEXT: ret <3 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2SQRT:%.*]] = call <3 x float> @_Z4sqrtDv3_f(<3 x float> [[X]]) +; CHECK-NEXT: ret <3 x float> [[__ROOTN2SQRT]] ; entry: %call = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> %x, <3 x i32> ) @@ -692,8 +683,8 @@ define <4 x float> @test_rootn_v4f32__y_2(<4 x float> %x) { ; CHECK-LABEL: define <4 x float> @test_rootn_v4f32__y_2( ; CHECK-SAME: <4 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <4 x float> @_Z5rootnDv4_fDv4_i(<4 x float> [[X]], <4 x i32> ) -; CHECK-NEXT: ret <4 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2SQRT:%.*]] = call <4 x float> @_Z4sqrtDv4_f(<4 x float> [[X]]) +; CHECK-NEXT: ret <4 x float> [[__ROOTN2SQRT]] ; entry: %call = tail call <4 x float> @_Z5rootnDv4_fDv4_i(<4 x float> %x, <4 x i32> ) @@ -704,8 +695,8 @@ define <8 x float> @test_rootn_v8f32__y_2(<8 x float> %x) { ; CHECK-LABEL: define <8 x float> @test_rootn_v8f32__y_2( ; CHECK-SAME: <8 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <8 x float> @_Z5rootnDv8_fDv8_i(<8 x float> [[X]], <8 x i32> ) -; CHECK-NEXT: ret <8 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2SQRT:%.*]] = call <8 x float> @_Z4sqrtDv8_f(<8 x float> [[X]]) +; CHECK-NEXT: ret <8 x float> [[__ROOTN2SQRT]] ; entry: %call = tail call <8 x float> @_Z5rootnDv8_fDv8_i(<8 x float> %x, <8 x i32> ) @@ -716,8 +707,8 @@ define <16 x float> @test_rootn_v16f32__y_2(<16 x float> %x) { ; CHECK-LABEL: define <16 x float> @test_rootn_v16f32__y_2( ; CHECK-SAME: <16 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <16 x float> @_Z5rootnDv16_fDv16_i(<16 x float> [[X]], <16 x i32> ) -; CHECK-NEXT: ret <16 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2SQRT:%.*]] = call <16 x float> @_Z4sqrtDv16_f(<16 x float> [[X]]) +; CHECK-NEXT: ret <16 x float> [[__ROOTN2SQRT]] ; entry: %call = tail call <16 x float> @_Z5rootnDv16_fDv16_i(<16 x float> %x, <16 x i32> ) @@ -740,8 +731,8 @@ define <2 x float> @test_rootn_v2f32__y_3(<2 x float> %x) { ; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_3( ; CHECK-SAME: <2 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> ) -; CHECK-NEXT: ret <2 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2CBRT:%.*]] = call <2 x float> @_Z4cbrtDv2_f(<2 x float> [[X]]) +; CHECK-NEXT: ret <2 x float> [[__ROOTN2CBRT]] ; entry: %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> ) @@ -764,8 +755,8 @@ define <2 x float> @test_rootn_v2f32__y_nonsplat_2_poison(<2 x float> %x) { ; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_nonsplat_2_poison( ; CHECK-SAME: <2 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> ) -; CHECK-NEXT: ret <2 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2SQRT:%.*]] = call <2 x float> @_Z4sqrtDv2_f(<2 x float> [[X]]) +; CHECK-NEXT: ret <2 x float> [[__ROOTN2SQRT]] ; entry: %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> ) @@ -800,8 +791,8 @@ define <2 x float> @test_rootn_v2f32__y_neg1(<2 x float> %x) { ; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_neg1( ; CHECK-SAME: <2 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> ) -; CHECK-NEXT: ret <2 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2DIV:%.*]] = fdiv <2 x float> , [[X]] +; CHECK-NEXT: ret <2 x float> [[__ROOTN2DIV]] ; entry: %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> ) @@ -812,8 +803,8 @@ define <3 x float> @test_rootn_v3f32__y_neg1(<3 x float> %x) { ; CHECK-LABEL: define <3 x float> @test_rootn_v3f32__y_neg1( ; CHECK-SAME: <3 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> [[X]], <3 x i32> ) -; CHECK-NEXT: ret <3 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2DIV:%.*]] = fdiv <3 x float> , [[X]] +; CHECK-NEXT: ret <3 x float> [[__ROOTN2DIV]] ; entry: %call = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> %x, <3 x i32> ) @@ -824,8 +815,8 @@ define <3 x float> @test_rootn_v3f32__y_neg1_undef(<3 x float> %x) { ; CHECK-LABEL: define <3 x float> @test_rootn_v3f32__y_neg1_undef( ; CHECK-SAME: <3 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> [[X]], <3 x i32> ) -; CHECK-NEXT: ret <3 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2DIV:%.*]] = fdiv <3 x float> , [[X]] +; CHECK-NEXT: ret <3 x float> [[__ROOTN2DIV]] ; entry: %call = tail call <3 x float> @_Z5rootnDv3_fDv3_i(<3 x float> %x, <3 x i32> ) @@ -836,8 +827,8 @@ define <4 x float> @test_rootn_v4f32__y_neg1(<4 x float> %x) { ; CHECK-LABEL: define <4 x float> @test_rootn_v4f32__y_neg1( ; CHECK-SAME: <4 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <4 x float> @_Z5rootnDv4_fDv4_i(<4 x float> [[X]], <4 x i32> ) -; CHECK-NEXT: ret <4 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2DIV:%.*]] = fdiv <4 x float> , [[X]] +; CHECK-NEXT: ret <4 x float> [[__ROOTN2DIV]] ; entry: %call = tail call <4 x float> @_Z5rootnDv4_fDv4_i(<4 x float> %x, <4 x i32> ) @@ -848,8 +839,8 @@ define <8 x float> @test_rootn_v8f32__y_neg1(<8 x float> %x) { ; CHECK-LABEL: define <8 x float> @test_rootn_v8f32__y_neg1( ; CHECK-SAME: <8 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <8 x float> @_Z5rootnDv8_fDv8_i(<8 x float> [[X]], <8 x i32> ) -; CHECK-NEXT: ret <8 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2DIV:%.*]] = fdiv <8 x float> , [[X]] +; CHECK-NEXT: ret <8 x float> [[__ROOTN2DIV]] ; entry: %call = tail call <8 x float> @_Z5rootnDv8_fDv8_i(<8 x float> %x, <8 x i32> ) @@ -860,8 +851,8 @@ define <16 x float> @test_rootn_v16f32__y_neg1(<16 x float> %x) { ; CHECK-LABEL: define <16 x float> @test_rootn_v16f32__y_neg1( ; CHECK-SAME: <16 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <16 x float> @_Z5rootnDv16_fDv16_i(<16 x float> [[X]], <16 x i32> ) -; CHECK-NEXT: ret <16 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2DIV:%.*]] = fdiv <16 x float> , [[X]] +; CHECK-NEXT: ret <16 x float> [[__ROOTN2DIV]] ; entry: %call = tail call <16 x float> @_Z5rootnDv16_fDv16_i(<16 x float> %x, <16 x i32> ) @@ -932,8 +923,8 @@ define <2 x float> @test_rootn_v2f32__y_neg2(<2 x float> %x) { ; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_neg2( ; CHECK-SAME: <2 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> ) -; CHECK-NEXT: ret <2 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call <2 x float> @_Z5rsqrtDv2_f(<2 x float> [[X]]) +; CHECK-NEXT: ret <2 x float> [[__ROOTN2RSQRT]] ; entry: %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> ) @@ -944,8 +935,8 @@ define <2 x float> @test_rootn_v2f32__y_neg2__flags(<2 x float> %x) { ; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_neg2__flags( ; CHECK-SAME: <2 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call nnan nsz <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> ) -; CHECK-NEXT: ret <2 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call nnan nsz <2 x float> @_Z5rsqrtDv2_f(<2 x float> [[X]]) +; CHECK-NEXT: ret <2 x float> [[__ROOTN2RSQRT]] ; entry: %call = tail call nsz nnan <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> ) @@ -956,8 +947,8 @@ define <2 x float> @test_rootn_v2f32__y_neg2__strictfp(<2 x float> %x) #1 { ; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_neg2__strictfp( ; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> ) #[[ATTR0]] -; CHECK-NEXT: ret <2 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call <2 x float> @_Z5rsqrtDv2_f(<2 x float> [[X]]) #[[ATTR0]] +; CHECK-NEXT: ret <2 x float> [[__ROOTN2RSQRT]] ; entry: %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> ) #1 @@ -1266,8 +1257,8 @@ define <2 x float> @test_rootn_afn_nnan_ninf_v2f32__y_3(<2 x float> %x) { ; CHECK-LABEL: define <2 x float> @test_rootn_afn_nnan_ninf_v2f32__y_3( ; CHECK-SAME: <2 x float> [[X:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call nnan ninf afn <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> ) -; CHECK-NEXT: ret <2 x float> [[CALL]] +; CHECK-NEXT: [[__ROOTN2CBRT:%.*]] = call nnan ninf afn <2 x float> @_Z4cbrtDv2_f(<2 x float> [[X]]) +; CHECK-NEXT: ret <2 x float> [[__ROOTN2CBRT]] ; entry: %call = tail call afn nnan ninf <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> ) -- GitLab From 0a15574eec7715e09b6fd52d3cd9a4f6e2b797e9 Mon Sep 17 00:00:00 2001 From: Jacob Lambert Date: Mon, 20 May 2024 09:42:09 -0700 Subject: [PATCH 099/793] [NFC][amdgpuarch] Correct file names in file header comments (#92294) --- clang/tools/amdgpu-arch/AMDGPUArchByHIP.cpp | 2 +- clang/tools/amdgpu-arch/AMDGPUArchByHSA.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/tools/amdgpu-arch/AMDGPUArchByHIP.cpp b/clang/tools/amdgpu-arch/AMDGPUArchByHIP.cpp index 7c9071be0918..7338872dbf32 100644 --- a/clang/tools/amdgpu-arch/AMDGPUArchByHIP.cpp +++ b/clang/tools/amdgpu-arch/AMDGPUArchByHIP.cpp @@ -1,4 +1,4 @@ -//===- AMDGPUArch.cpp - list AMDGPU installed ----------*- C++ -*---------===// +//===- AMDGPUArchByHIP.cpp - list AMDGPU installed ----------*- C++ -*-----===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/tools/amdgpu-arch/AMDGPUArchByHSA.cpp b/clang/tools/amdgpu-arch/AMDGPUArchByHSA.cpp index f82a4890f465..432f2c414ed2 100644 --- a/clang/tools/amdgpu-arch/AMDGPUArchByHSA.cpp +++ b/clang/tools/amdgpu-arch/AMDGPUArchByHSA.cpp @@ -1,4 +1,4 @@ -//===- AMDGPUArchLinux.cpp - list AMDGPU installed ------*- C++ -*---------===// +//===- AMDGPUArchByHSA.cpp - list AMDGPU installed ------*- C++ -*---------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. -- GitLab From 097e96d0d1ad9cceb461bb3487af0a2ec42176e4 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 20 May 2024 09:30:56 -0700 Subject: [PATCH 100/793] [LegalizeTypes] Use VP_AND for zext_inreg in PromoteIntRes_VPFunnelShift. I may eventually add getVPZeroExtendInReg to SelectionDAG if there are other cases, but for now just hardcode it. --- llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | 6 ++++-- llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll | 8 ++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 98f64947bcab..7d3be7299523 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -1511,8 +1511,10 @@ SDValue DAGTypeLegalizer::PromoteIntRes_VPFunnelShift(SDNode *N) { !TLI.isOperationLegalOrCustom(Opcode, VT)) { SDValue HiShift = DAG.getConstant(OldBits, DL, VT); Hi = DAG.getNode(ISD::VP_SHL, DL, VT, Hi, HiShift, Mask, EVL); - // FIXME: Replace it by vp operations. - Lo = DAG.getZeroExtendInReg(Lo, DL, OldVT); + APInt Imm = APInt::getLowBitsSet(VT.getScalarSizeInBits(), + OldVT.getScalarSizeInBits()); + Lo = DAG.getNode(ISD::VP_AND, DL, VT, Lo, DAG.getConstant(Imm, DL, VT), + Mask, EVL); SDValue Res = DAG.getNode(ISD::VP_OR, DL, VT, Hi, Lo, Mask, EVL); Res = DAG.getNode(IsFSHR ? ISD::VP_LSHR : ISD::VP_SHL, DL, VT, Res, Amt, Mask, EVL); diff --git a/llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll b/llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll index 249f765971b0..84fb777c64b8 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fshr-fshl-vp.ll @@ -1318,10 +1318,8 @@ define @fshr_v1i4( %a, %b, ; CHECK-NEXT: li a1, 4 ; CHECK-NEXT: vsetvli zero, a0, e8, mf8, ta, ma ; CHECK-NEXT: vremu.vx v10, v10, a1, v0.t +; CHECK-NEXT: vand.vi v9, v9, 15, v0.t ; CHECK-NEXT: vsll.vi v8, v8, 4, v0.t -; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; CHECK-NEXT: vand.vi v9, v9, 15 -; CHECK-NEXT: vsetvli zero, a0, e8, mf8, ta, ma ; CHECK-NEXT: vor.vv v8, v8, v9, v0.t ; CHECK-NEXT: vsrl.vv v8, v8, v10, v0.t ; CHECK-NEXT: vand.vi v8, v8, 15, v0.t @@ -1343,10 +1341,8 @@ define @fshl_v1i4( %a, %b, ; CHECK-NEXT: li a1, 4 ; CHECK-NEXT: vsetvli zero, a0, e8, mf8, ta, ma ; CHECK-NEXT: vremu.vx v10, v10, a1, v0.t +; CHECK-NEXT: vand.vi v9, v9, 15, v0.t ; CHECK-NEXT: vsll.vi v8, v8, 4, v0.t -; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; CHECK-NEXT: vand.vi v9, v9, 15 -; CHECK-NEXT: vsetvli zero, a0, e8, mf8, ta, ma ; CHECK-NEXT: vor.vv v8, v8, v9, v0.t ; CHECK-NEXT: vsll.vv v8, v8, v10, v0.t ; CHECK-NEXT: vsrl.vi v8, v8, 4, v0.t -- GitLab From 9964c2c33d750d60b512d518899fa2147576f3f3 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Date: Mon, 20 May 2024 22:26:49 +0530 Subject: [PATCH 101/793] [MILR][NVVM] Fix missing semicolon in nvvm.barrier.arrive Op (#92769) This commit fixes the missing semicolon in the PTX codegen path where barrier id is provided for the NVVM BarrierArriveOp. Also, updated nvvm-to-llvm.mlir lit test to reflect the same Co-authored-by: pradeepku --- mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td | 2 +- mlir/test/Conversion/NVVMToLLVM/nvvm-to-llvm.mlir | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td index 7ffbc2d7922f..4daeeab09386 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td @@ -429,7 +429,7 @@ def NVVM_BarrierArriveOp : NVVM_PTXBuilder_Op<"barrier.arrive"> let extraClassDefinition = [{ std::string $cppClass::getPtx() { std::string ptx = "bar.arrive "; - if (getBarrierId()) { ptx += "%0, %1"; } + if (getBarrierId()) { ptx += "%0, %1;"; } else { ptx += "0, %0;"; } return ptx; } diff --git a/mlir/test/Conversion/NVVMToLLVM/nvvm-to-llvm.mlir b/mlir/test/Conversion/NVVMToLLVM/nvvm-to-llvm.mlir index 802760f8c899..1d56ca97b737 100644 --- a/mlir/test/Conversion/NVVMToLLVM/nvvm-to-llvm.mlir +++ b/mlir/test/Conversion/NVVMToLLVM/nvvm-to-llvm.mlir @@ -688,7 +688,7 @@ func.func @fence_proxy() { llvm.func @llvm_nvvm_barrier_arrive(%barID : i32, %numberOfThreads : i32) { // CHECK: llvm.inline_asm has_side_effects asm_dialect = att "bar.arrive 0, $0;", "r" %[[numberOfThreads]] : (i32) -> () nvvm.barrier.arrive number_of_threads = %numberOfThreads - // CHECK: llvm.inline_asm has_side_effects asm_dialect = att "bar.arrive $0, $1", "r,r" %[[barId]], %[[numberOfThreads]] : (i32, i32) -> () + // CHECK: llvm.inline_asm has_side_effects asm_dialect = att "bar.arrive $0, $1;", "r,r" %[[barId]], %[[numberOfThreads]] : (i32, i32) -> () nvvm.barrier.arrive id = %barID number_of_threads = %numberOfThreads llvm.return } -- GitLab From 4f5bc4bb55a8091ca9eb6dd016dcb2be82bf917a Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Mon, 20 May 2024 20:02:15 +0300 Subject: [PATCH 102/793] [clang][NFC] Rename `SemaRISCVVectorLookup.cpp` into `SemaRISCV.cpp` In preparation for #92682. --- clang/lib/Sema/CMakeLists.txt | 2 +- clang/lib/Sema/{SemaRISCVVectorLookup.cpp => SemaRISCV.cpp} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename clang/lib/Sema/{SemaRISCVVectorLookup.cpp => SemaRISCV.cpp} (100%) diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index 58e0a3b9679b..6b7742cae2db 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -60,7 +60,7 @@ add_clang_library(clangSema SemaOpenMP.cpp SemaOverload.cpp SemaPseudoObject.cpp - SemaRISCVVectorLookup.cpp + SemaRISCV.cpp SemaStmt.cpp SemaStmtAsm.cpp SemaStmtAttr.cpp diff --git a/clang/lib/Sema/SemaRISCVVectorLookup.cpp b/clang/lib/Sema/SemaRISCV.cpp similarity index 100% rename from clang/lib/Sema/SemaRISCVVectorLookup.cpp rename to clang/lib/Sema/SemaRISCV.cpp -- GitLab From d71f30a7f45c5a73fe551ea4ca48b11191e7b0e8 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Mon, 20 May 2024 20:03:22 +0300 Subject: [PATCH 103/793] [clang][NFC] Update the list of Core issues --- clang/www/cxx_dr_status.html | 38 +++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 5d517d358672..9d458330f537 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -12890,11 +12890,11 @@ and POD class Virtual bases in destructors and defaulted assignment operators Yes - + 2181 - drafting + C++20 Normative requirements in an informative Annex - Not resolved + Unknown 2182 @@ -17021,13 +17021,13 @@ objects 2869 - review + tentatively ready this in local classes Not resolved 2870 - review + tentatively ready Combining absent encoding-prefixes Not resolved @@ -17039,7 +17039,7 @@ objects 2872 - open + tentatively ready Linkage and unclear "can be referred to" Not resolved @@ -17051,25 +17051,25 @@ objects 2874 - open + tentatively ready Qualified declarations of partial specializations Not resolved 2875 - open - Missing support for round-tripping nullptr through indirection/address operators + tentatively ready + Missing support for round-tripping null pointer values through indirection/address operators Not resolved 2876 - open + tentatively ready Disambiguation of T x = delete("text") Not resolved 2877 - open + tentatively ready Type-only lookup for using-enum-declarator Not resolved @@ -17093,7 +17093,7 @@ objects 2881 - open + tentatively ready Type restrictions for the explicit object parameter of a lambda Not resolved @@ -17109,15 +17109,15 @@ objects Definition of "odr-usable" ignores lambda scopes Not resolved - + 2884 - open + dup Qualified declarations of partial specializations - Not resolved + Unknown 2885 - open + review Non-eligible trivial default constructors Not resolved @@ -17150,6 +17150,12 @@ objects open Defining members of local classes Not resolved + + + 2891 + review + Normative status of implementation limits + Not resolved -- GitLab From 0047df9af4a106560197850438d6543dcb87d839 Mon Sep 17 00:00:00 2001 From: Vyacheslav Levytskyy Date: Mon, 20 May 2024 19:05:25 +0200 Subject: [PATCH 104/793] [SPIR-V] reqd_work_group_size and work_group_size_hint metadata are correctly converted to the LocalSize and LocalSizeHint execution mode (#92552) The goal of this PR is to ensure that reqd_work_group_size and work_group_size_hint metadata are correctly converted to the LocalSize and LocalSizeHint execution mode. reqd_work_group_size and work_group_size_hint require 3 operands (see https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Execution_Mode), if metadata contains less operands, just add a default value (1). --- llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp | 20 +++++++---- .../execution-mode-reqd_work_group_size.ll | 35 +++++++++++++++++++ .../execution-mode-work_group_size_hint.ll | 34 ++++++++++++++++++ 3 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 llvm/test/CodeGen/SPIRV/execution-mode-reqd_work_group_size.ll create mode 100644 llvm/test/CodeGen/SPIRV/execution-mode-work_group_size_hint.ll diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp index ad0158086044..3206c264f99d 100644 --- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp @@ -69,7 +69,8 @@ public: void outputOpFunctionEnd(); void outputExtFuncDecls(); void outputExecutionModeFromMDNode(Register Reg, MDNode *Node, - SPIRV::ExecutionMode::ExecutionMode EM); + SPIRV::ExecutionMode::ExecutionMode EM, + unsigned ExpectMDOps, int64_t DefVal); void outputExecutionModeFromNumthreadsAttribute( const Register &Reg, const Attribute &Attr, SPIRV::ExecutionMode::ExecutionMode EM); @@ -422,12 +423,19 @@ static void addOpsFromMDNode(MDNode *MDN, MCInst &Inst, } void SPIRVAsmPrinter::outputExecutionModeFromMDNode( - Register Reg, MDNode *Node, SPIRV::ExecutionMode::ExecutionMode EM) { + Register Reg, MDNode *Node, SPIRV::ExecutionMode::ExecutionMode EM, + unsigned ExpectMDOps, int64_t DefVal) { MCInst Inst; Inst.setOpcode(SPIRV::OpExecutionMode); Inst.addOperand(MCOperand::createReg(Reg)); Inst.addOperand(MCOperand::createImm(static_cast(EM))); addOpsFromMDNode(Node, Inst, MAI); + // reqd_work_group_size and work_group_size_hint require 3 operands, + // if metadata contains less operands, just add a default value + unsigned NodeSz = Node->getNumOperands(); + if (ExpectMDOps > 0 && NodeSz < ExpectMDOps) + for (unsigned i = NodeSz; i < ExpectMDOps; ++i) + Inst.addOperand(MCOperand::createImm(DefVal)); outputMCInst(Inst); } @@ -473,17 +481,17 @@ void SPIRVAsmPrinter::outputExecutionMode(const Module &M) { Register FReg = MAI->getFuncReg(&F); assert(FReg.isValid()); if (MDNode *Node = F.getMetadata("reqd_work_group_size")) - outputExecutionModeFromMDNode(FReg, Node, - SPIRV::ExecutionMode::LocalSize); + outputExecutionModeFromMDNode(FReg, Node, SPIRV::ExecutionMode::LocalSize, + 3, 1); if (Attribute Attr = F.getFnAttribute("hlsl.numthreads"); Attr.isValid()) outputExecutionModeFromNumthreadsAttribute( FReg, Attr, SPIRV::ExecutionMode::LocalSize); if (MDNode *Node = F.getMetadata("work_group_size_hint")) outputExecutionModeFromMDNode(FReg, Node, - SPIRV::ExecutionMode::LocalSizeHint); + SPIRV::ExecutionMode::LocalSizeHint, 3, 1); if (MDNode *Node = F.getMetadata("intel_reqd_sub_group_size")) outputExecutionModeFromMDNode(FReg, Node, - SPIRV::ExecutionMode::SubgroupSize); + SPIRV::ExecutionMode::SubgroupSize, 0, 0); if (MDNode *Node = F.getMetadata("vec_type_hint")) { MCInst Inst; Inst.setOpcode(SPIRV::OpExecutionMode); diff --git a/llvm/test/CodeGen/SPIRV/execution-mode-reqd_work_group_size.ll b/llvm/test/CodeGen/SPIRV/execution-mode-reqd_work_group_size.ll new file mode 100644 index 000000000000..6e36b0bd5b9d --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/execution-mode-reqd_work_group_size.ll @@ -0,0 +1,35 @@ +; From Khronos Translator's test case: test/reqd_work_group_size_md.ll + +; The purpose of this test is to check that the reqd_work_group_size metadata +; is correctly converted to the LocalSize execution mode for the kernels it is +; applied to. + +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpMemoryModel +; CHECK-DAG: OpEntryPoint Kernel %[[#ENTRY1:]] "test1" +; CHECK-DAG: OpEntryPoint Kernel %[[#ENTRY2:]] "test2" +; CHECK-DAG: OpEntryPoint Kernel %[[#ENTRY3:]] "test3" +; CHECK-DAG: OpExecutionMode %[[#ENTRY1]] LocalSize 1 2 3 +; CHECK-DAG: OpExecutionMode %[[#ENTRY2]] LocalSize 2 3 1 +; CHECK-DAG: OpExecutionMode %[[#ENTRY3]] LocalSize 3 1 1 + +define spir_kernel void @test1() !reqd_work_group_size !1 { +entry: + ret void +} + +define spir_kernel void @test2() !reqd_work_group_size !2 { +entry: + ret void +} + +define spir_kernel void @test3() !reqd_work_group_size !3 { +entry: + ret void +} + +!1 = !{i32 1, i32 2, i32 3} +!2 = !{i32 2, i32 3} +!3 = !{i32 3} diff --git a/llvm/test/CodeGen/SPIRV/execution-mode-work_group_size_hint.ll b/llvm/test/CodeGen/SPIRV/execution-mode-work_group_size_hint.ll new file mode 100644 index 000000000000..f2c43d3748af --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/execution-mode-work_group_size_hint.ll @@ -0,0 +1,34 @@ +; From Khronos Translator's test case: test/reqd_work_group_size_md.ll + +; The purpose of this test is to check that the work_group_size_hint metadata +; is correctly converted to the LocalSizeHint execution mode. + +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpMemoryModel +; CHECK-DAG: OpEntryPoint Kernel %[[#ENTRY1:]] "test1" +; CHECK-DAG: OpEntryPoint Kernel %[[#ENTRY2:]] "test2" +; CHECK-DAG: OpEntryPoint Kernel %[[#ENTRY3:]] "test3" +; CHECK-DAG: OpExecutionMode %[[#ENTRY1]] LocalSizeHint 1 2 3 +; CHECK-DAG: OpExecutionMode %[[#ENTRY2]] LocalSizeHint 2 3 1 +; CHECK-DAG: OpExecutionMode %[[#ENTRY3]] LocalSizeHint 3 1 1 + +define spir_kernel void @test1() !work_group_size_hint !1 { +entry: + ret void +} + +define spir_kernel void @test2() !work_group_size_hint !2 { +entry: + ret void +} + +define spir_kernel void @test3() !work_group_size_hint !3 { +entry: + ret void +} + +!1 = !{i32 1, i32 2, i32 3} +!2 = !{i32 2, i32 3} +!3 = !{i32 3} -- GitLab From 50be0b1b967eeb479989ed26c13d17a53845dd1e Mon Sep 17 00:00:00 2001 From: Vyacheslav Levytskyy Date: Mon, 20 May 2024 19:10:03 +0200 Subject: [PATCH 105/793] [SPIR-V] Ensure that internal intrinsic functions "ptrcast" for PHI's operand are inserted at the correct positions (#92536) The goal of the PR is to ensure that newly inserted `ptrcast` internal intrinsic functions are inserted at the correct positions, and don't break rules of instruction domination and PHI nodes grouping at top of basic block. --- llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 17 +++- .../CodeGen/SPIRV/phi-ptrcast-dominate.ll | 94 +++++++++++++++++++ 2 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 llvm/test/CodeGen/SPIRV/phi-ptrcast-dominate.ll diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp index 32df2403dfe5..a1a08c5c699b 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -489,10 +489,6 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(Instruction *I) { Type *Ty = GR->findDeducedElementType(Op); if (Ty == KnownElemTy) continue; - if (Instruction *User = dyn_cast(Op->use_begin()->get())) - setInsertPointSkippingPhis(B, User->getNextNode()); - else - setInsertPointSkippingPhis(B, I); Value *OpTyVal = Constant::getNullValue(KnownElemTy); Type *OpTy = Op->getType(); if (!Ty) { @@ -500,6 +496,8 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(Instruction *I) { // check if there is existing Intrinsic::spv_assign_ptr_type instruction auto It = AssignPtrTypeInstr.find(Op); if (It == AssignPtrTypeInstr.end()) { + Instruction *User = dyn_cast(Op->use_begin()->get()); + setInsertPointSkippingPhis(B, User ? User->getNextNode() : I); CallInst *CI = buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {OpTy}, OpTyVal, Op, {B.getInt32(getPointerAddressSpace(OpTy))}, B); @@ -511,6 +509,17 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(Instruction *I) { Ctx, MDNode::get(Ctx, ValueAsMetadata::getConstant(OpTyVal)))); } } else { + if (auto *OpI = dyn_cast(Op)) { + // spv_ptrcast's argument Op denotes an instruction that generates + // a value, and we may use getInsertionPointAfterDef() + B.SetInsertPoint(*OpI->getInsertionPointAfterDef()); + B.SetCurrentDebugLocation(OpI->getDebugLoc()); + } else if (auto *OpA = dyn_cast(Op)) { + B.SetInsertPointPastAllocas(OpA->getParent()); + B.SetCurrentDebugLocation(DebugLoc()); + } else { + B.SetInsertPoint(F->getEntryBlock().getFirstNonPHIOrDbgOrAlloca()); + } SmallVector Types = {OpTy, OpTy}; MetadataAsValue *VMD = MetadataAsValue::get( Ctx, MDNode::get(Ctx, ValueAsMetadata::getConstant(OpTyVal))); diff --git a/llvm/test/CodeGen/SPIRV/phi-ptrcast-dominate.ll b/llvm/test/CodeGen/SPIRV/phi-ptrcast-dominate.ll new file mode 100644 index 000000000000..2cd321b05a40 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/phi-ptrcast-dominate.ll @@ -0,0 +1,94 @@ +; The goal of the test is to check that newly inserted `ptrcast` internal +; intrinsic functions for PHI's operands are inserted at the correct +; positions, and don't break rules of instruction domination and PHI nodes +; grouping at top of basic block. + +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: OpName %[[#Case1:]] "case1" +; CHECK-DAG: OpName %[[#Case2:]] "case2" +; CHECK-DAG: OpName %[[#Case3:]] "case3" +; CHECK: %[[#Case1]] = OpFunction +; CHECK: OpBranchConditional +; CHECK: OpPhi +; CHECK: OpBranch +; CHECK-COUNT-2: OpBranchConditional +; CHECK: OpFunctionEnd +; CHECK: %[[#Case2]] = OpFunction +; CHECK: OpBranchConditional +; CHECK: OpPhi +; CHECK: OpBranch +; CHECK-COUNT-2: OpBranchConditional +; CHECK: OpFunctionEnd +; CHECK: %[[#Case3]] = OpFunction +; CHECK: OpBranchConditional +; CHECK: OpPhi +; CHECK: OpBranch +; CHECK: OpInBoundsPtrAccessChain +; CHECK: OpBranchConditional +; CHECK: OpInBoundsPtrAccessChain +; CHECK: OpBranchConditional +; CHECK: OpFunctionEnd + +%struct1 = type { i64 } +%struct2 = type { i64, i64 } + +@.str.1 = private unnamed_addr addrspace(1) constant [3 x i8] c"OK\00", align 1 +@.str.2 = private unnamed_addr addrspace(1) constant [6 x i8] c"WRONG\00", align 1 + +define spir_func void @case1(i1 %b1, i1 %b2, i1 %b3) { +entry: + br i1 %b1, label %l1, label %l2 + +l1: + %str = phi ptr addrspace(1) [ @.str.1, %entry ], [ @.str.2, %l2 ], [ @.str.2, %l3 ] + br label %exit + +l2: + br i1 %b2, label %l1, label %l3 + +l3: + br i1 %b3, label %l1, label %exit + +exit: + ret void +} + +define spir_func void @case2(i1 %b1, i1 %b2, i1 %b3, ptr addrspace(1) byval(%struct1) %str1, ptr addrspace(1) byval(%struct2) %str2) { +entry: + br i1 %b1, label %l1, label %l2 + +l1: + %str = phi ptr addrspace(1) [ %str1, %entry ], [ %str2, %l2 ], [ %str2, %l3 ] + br label %exit + +l2: + br i1 %b2, label %l1, label %l3 + +l3: + br i1 %b3, label %l1, label %exit + +exit: + ret void +} + +define spir_func void @case3(i1 %b1, i1 %b2, i1 %b3, ptr addrspace(1) byval(%struct1) %_arg_str1, ptr addrspace(1) byval(%struct2) %_arg_str2) { +entry: + br i1 %b1, label %l1, label %l2 + +l1: + %str = phi ptr addrspace(1) [ %_arg_str1, %entry ], [ %str2, %l2 ], [ %str3, %l3 ] + br label %exit + +l2: + %str2 = getelementptr inbounds %struct2, ptr addrspace(1) %_arg_str2, i32 1 + br i1 %b2, label %l1, label %l3 + +l3: + %str3 = getelementptr inbounds %struct2, ptr addrspace(1) %_arg_str2, i32 2 + br i1 %b3, label %l1, label %exit + +exit: + ret void +} -- GitLab From 1de1f775b55bb5c4c739e8f7ac78e7f59f2645fb Mon Sep 17 00:00:00 2001 From: Jeremy Kun Date: Mon, 20 May 2024 10:14:48 -0700 Subject: [PATCH 106/793] [mlir] [openmp] fix bazel build (#92790) Co-authored-by: Jeremy Kun --- utils/bazel/llvm-project-overlay/mlir/BUILD.bazel | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index 71fca298e9b9..fc14e93b3686 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -10145,7 +10145,11 @@ td_library( srcs = [ "include/mlir/Dialect/OpenACCMPCommon/Interfaces/AtomicInterfaces.td", "include/mlir/Dialect/OpenMP/OmpCommon.td", + "include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td", + "include/mlir/Dialect/OpenMP/OpenMPDialect.td", + "include/mlir/Dialect/OpenMP/OpenMPEnums.td", "include/mlir/Dialect/OpenMP/OpenMPOps.td", + "include/mlir/Dialect/OpenMP/OpenMPOpBase.td", "include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td", "include/mlir/Dialect/OpenMP/OpenMPTypeInterfaces.td", ], -- GitLab From 3575d23ca866e0510b322e4520d6cbcebee18c22 Mon Sep 17 00:00:00 2001 From: Ahmed Bougacha Date: Mon, 20 May 2024 10:23:04 -0700 Subject: [PATCH 107/793] [clang][CodeGen] Remove unused LValue::getAddress CGF arg. (#92465) This is in effect a revert of f139ae3d93797, as we have since gained a more sophisticated way of doing extra IRGen with the addition of RawAddress in #86923. --- clang/lib/CodeGen/CGAtomic.cpp | 14 +- clang/lib/CodeGen/CGBlocks.cpp | 2 +- clang/lib/CodeGen/CGBuiltin.cpp | 10 +- clang/lib/CodeGen/CGCall.cpp | 28 ++-- clang/lib/CodeGen/CGClass.cpp | 18 +-- clang/lib/CodeGen/CGDecl.cpp | 34 +++-- clang/lib/CodeGen/CGDeclCXX.cpp | 2 +- clang/lib/CodeGen/CGException.cpp | 3 +- clang/lib/CodeGen/CGExpr.cpp | 93 +++++++------- clang/lib/CodeGen/CGExprAgg.cpp | 45 ++++--- clang/lib/CodeGen/CGExprCXX.cpp | 16 +-- clang/lib/CodeGen/CGExprComplex.cpp | 10 +- clang/lib/CodeGen/CGExprScalar.cpp | 20 +-- clang/lib/CodeGen/CGNonTrivialStruct.cpp | 18 +-- clang/lib/CodeGen/CGObjC.cpp | 20 +-- clang/lib/CodeGen/CGOpenMPRuntime.cpp | 91 +++++++------ clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp | 16 +-- clang/lib/CodeGen/CGStmt.cpp | 13 +- clang/lib/CodeGen/CGStmtOpenMP.cpp | 156 +++++++++++------------ clang/lib/CodeGen/CGValue.h | 13 +- clang/lib/CodeGen/CodeGenFunction.cpp | 4 +- clang/lib/CodeGen/Targets/NVPTX.cpp | 2 +- clang/lib/CodeGen/Targets/X86.cpp | 2 +- 23 files changed, 302 insertions(+), 328 deletions(-) diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index 07452b18a85e..fbf942d06ca6 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -150,7 +150,7 @@ namespace { Address getAtomicAddress() const { llvm::Type *ElTy; if (LVal.isSimple()) - ElTy = LVal.getAddress(CGF).getElementType(); + ElTy = LVal.getAddress().getElementType(); else if (LVal.isBitField()) ElTy = LVal.getBitFieldAddress().getElementType(); else if (LVal.isVectorElt()) @@ -363,7 +363,7 @@ bool AtomicInfo::requiresMemSetZero(llvm::Type *type) const { bool AtomicInfo::emitMemSetZeroIfNecessary() const { assert(LVal.isSimple()); - Address addr = LVal.getAddress(CGF); + Address addr = LVal.getAddress(); if (!requiresMemSetZero(addr.getElementType())) return false; @@ -1603,7 +1603,7 @@ Address AtomicInfo::materializeRValue(RValue rvalue) const { LValue TempLV = CGF.MakeAddrLValue(CreateTempAlloca(), getAtomicType()); AtomicInfo Atomics(CGF, TempLV); Atomics.emitCopyIntoMemory(rvalue); - return TempLV.getAddress(CGF); + return TempLV.getAddress(); } llvm::Value *AtomicInfo::getScalarRValValueOrNull(RValue RVal) const { @@ -1951,7 +1951,7 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, // maybe for address-space qualification. assert(!rvalue.isAggregate() || rvalue.getAggregateAddress().getElementType() == - dest.getAddress(*this).getElementType()); + dest.getAddress().getElementType()); AtomicInfo atomics(*this, dest); LValue LVal = atomics.getAtomicLValue(); @@ -2024,10 +2024,10 @@ std::pair CodeGenFunction::EmitAtomicCompareExchange( // maybe for address-space qualification. assert(!Expected.isAggregate() || Expected.getAggregateAddress().getElementType() == - Obj.getAddress(*this).getElementType()); + Obj.getAddress().getElementType()); assert(!Desired.isAggregate() || Desired.getAggregateAddress().getElementType() == - Obj.getAddress(*this).getElementType()); + Obj.getAddress().getElementType()); AtomicInfo Atomics(*this, Obj); return Atomics.EmitAtomicCompareExchange(Expected, Desired, Success, Failure, @@ -2068,7 +2068,7 @@ void CodeGenFunction::EmitAtomicInit(Expr *init, LValue dest) { // Evaluate the expression directly into the destination. AggValueSlot slot = AggValueSlot::forLValue( - dest, *this, AggValueSlot::IsNotDestructed, + dest, AggValueSlot::IsNotDestructed, AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap, Zeroed ? AggValueSlot::IsZeroed : AggValueSlot::IsNotZeroed); diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 2742c39965b2..bf50f2025de5 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -927,7 +927,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { /*RefersToEnclosingVariableOrCapture*/ CI.isNested(), type.getNonReferenceType(), VK_LValue, SourceLocation()); - src = EmitDeclRefLValue(&declRef).getAddress(*this); + src = EmitDeclRefLValue(&declRef).getAddress(); }; // For byrefs, we just write the pointer to the byref struct into diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index e251091c6ce3..ba94bf89e475 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -5609,8 +5609,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, llvm::Value *Queue = EmitScalarExpr(E->getArg(0)); llvm::Value *Flags = EmitScalarExpr(E->getArg(1)); LValue NDRangeL = EmitAggExprToLValue(E->getArg(2)); - llvm::Value *Range = NDRangeL.getAddress(*this).emitRawPointer(*this); - llvm::Type *RangeTy = NDRangeL.getAddress(*this).getType(); + llvm::Value *Range = NDRangeL.getAddress().emitRawPointer(*this); + llvm::Type *RangeTy = NDRangeL.getAddress().getType(); if (NumArgs == 4) { // The most basic form of the call with parameters: @@ -5629,7 +5629,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy); AttrBuilder B(Builder.getContext()); - B.addByValAttr(NDRangeL.getAddress(*this).getElementType()); + B.addByValAttr(NDRangeL.getAddress().getElementType()); llvm::AttributeList ByValAttrSet = llvm::AttributeList::get(CGM.getModule().getContext(), 3U, B); @@ -5817,7 +5817,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, llvm::Type *GenericVoidPtrTy = Builder.getPtrTy( getContext().getTargetAddressSpace(LangAS::opencl_generic)); LValue NDRangeL = EmitAggExprToLValue(E->getArg(0)); - llvm::Value *NDRange = NDRangeL.getAddress(*this).emitRawPointer(*this); + llvm::Value *NDRange = NDRangeL.getAddress().emitRawPointer(*this); auto Info = CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(1)); Value *Kernel = @@ -21592,7 +21592,7 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID, // Handle aggregate argument, namely RVV tuple types in segment load/store if (hasAggregateEvaluationKind(E->getArg(i)->getType())) { LValue L = EmitAggExprToLValue(E->getArg(i)); - llvm::Value *AggValue = Builder.CreateLoad(L.getAddress(*this)); + llvm::Value *AggValue = Builder.CreateLoad(L.getAddress()); Ops.push_back(AggValue); continue; } diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 1b4ca2a8b2fe..cc626844f424 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1051,12 +1051,12 @@ void CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV, auto Exp = getTypeExpansion(Ty, getContext()); if (auto CAExp = dyn_cast(Exp.get())) { forConstantArrayExpansion( - *this, CAExp, LV.getAddress(*this), [&](Address EltAddr) { + *this, CAExp, LV.getAddress(), [&](Address EltAddr) { LValue LV = MakeAddrLValue(EltAddr, CAExp->EltTy); ExpandTypeFromArgs(CAExp->EltTy, LV, AI); }); } else if (auto RExp = dyn_cast(Exp.get())) { - Address This = LV.getAddress(*this); + Address This = LV.getAddress(); for (const CXXBaseSpecifier *BS : RExp->Bases) { // Perform a single step derived-to-base conversion. Address Base = @@ -1088,7 +1088,7 @@ void CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV, // pointer type they use (see D118744). Once clang uses opaque pointers // all LLVM pointer types will be the same and we can remove this check. if (Arg->getType()->isPointerTy()) { - Address Addr = LV.getAddress(*this); + Address Addr = LV.getAddress(); Arg = Builder.CreateBitCast(Arg, Addr.getElementType()); } EmitStoreOfScalar(Arg, LV); @@ -1101,7 +1101,7 @@ void CodeGenFunction::ExpandTypeToArgs( SmallVectorImpl &IRCallArgs, unsigned &IRCallArgPos) { auto Exp = getTypeExpansion(Ty, getContext()); if (auto CAExp = dyn_cast(Exp.get())) { - Address Addr = Arg.hasLValue() ? Arg.getKnownLValue().getAddress(*this) + Address Addr = Arg.hasLValue() ? Arg.getKnownLValue().getAddress() : Arg.getKnownRValue().getAggregateAddress(); forConstantArrayExpansion( *this, CAExp, Addr, [&](Address EltAddr) { @@ -1112,7 +1112,7 @@ void CodeGenFunction::ExpandTypeToArgs( IRCallArgPos); }); } else if (auto RExp = dyn_cast(Exp.get())) { - Address This = Arg.hasLValue() ? Arg.getKnownLValue().getAddress(*this) + Address This = Arg.hasLValue() ? Arg.getKnownLValue().getAddress() : Arg.getKnownRValue().getAggregateAddress(); for (const CXXBaseSpecifier *BS : RExp->Bases) { // Perform a single step derived-to-base conversion. @@ -4136,7 +4136,7 @@ static bool isProvablyNonNull(Address Addr, CodeGenFunction &CGF) { static void emitWriteback(CodeGenFunction &CGF, const CallArgList::Writeback &writeback) { const LValue &srcLV = writeback.Source; - Address srcAddr = srcLV.getAddress(CGF); + Address srcAddr = srcLV.getAddress(); assert(!isProvablyNull(srcAddr.getBasePointer()) && "shouldn't have writeback for provably null argument"); @@ -4243,7 +4243,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, CRE->getSubExpr()->getType()->castAs()->getPointeeType(); srcLV = CGF.MakeAddrLValue(srcAddr, srcAddrType); } - Address srcAddr = srcLV.getAddress(CGF); + Address srcAddr = srcLV.getAddress(); // The dest and src types don't necessarily match in LLVM terms // because of the crazy ObjC compatibility rules. @@ -4649,7 +4649,7 @@ RValue CallArg::getRValue(CodeGenFunction &CGF) const { CGF.EmitAggregateCopy(Copy, LV, Ty, AggValueSlot::DoesNotOverlap, LV.isVolatile()); IsUsed = true; - return RValue::getAggregate(Copy.getAddress(CGF)); + return RValue::getAggregate(Copy.getAddress()); } void CallArg::copyInto(CodeGenFunction &CGF, Address Addr) const { @@ -4659,7 +4659,7 @@ void CallArg::copyInto(CodeGenFunction &CGF, Address Addr) const { else if (!HasLV && RV.isComplex()) CGF.EmitStoreOfComplex(RV.getComplexVal(), Dst, /*init=*/true); else { - auto Addr = HasLV ? LV.getAddress(CGF) : RV.getAggregateAddress(); + auto Addr = HasLV ? LV.getAddress() : RV.getAggregateAddress(); LValue SrcLV = CGF.MakeAddrLValue(Addr, Ty); // We assume that call args are never copied into subobjects. CGF.EmitAggregateCopy(Dst, SrcLV, Ty, AggValueSlot::DoesNotOverlap, @@ -5147,7 +5147,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(getTarget().getTriple().getArch() == llvm::Triple::x86); if (I->isAggregate()) { RawAddress Addr = I->hasLValue() - ? I->getKnownLValue().getAddress(*this) + ? I->getKnownLValue().getAddress() : I->getKnownRValue().getAggregateAddress(); llvm::Instruction *Placeholder = cast(Addr.getPointer()); @@ -5213,7 +5213,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // 3. If the argument is byval, but RV is not located in default // or alloca address space. Address Addr = I->hasLValue() - ? I->getKnownLValue().getAddress(*this) + ? I->getKnownLValue().getAddress() : I->getKnownRValue().getAggregateAddress(); CharUnits Align = ArgInfo.getIndirectAlign(); const llvm::DataLayout *TD = &CGM.getDataLayout(); @@ -5309,7 +5309,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, V = I->getKnownRValue().getScalarVal(); else V = Builder.CreateLoad( - I->hasLValue() ? I->getKnownLValue().getAddress(*this) + I->hasLValue() ? I->getKnownLValue().getAddress() : I->getKnownRValue().getAggregateAddress()); // Implement swifterror by copying into a new swifterror argument. @@ -5372,7 +5372,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, Src = CreateMemTemp(I->Ty, "coerce"); I->copyInto(*this, Src); } else { - Src = I->hasLValue() ? I->getKnownLValue().getAddress(*this) + Src = I->hasLValue() ? I->getKnownLValue().getAddress() : I->getKnownRValue().getAggregateAddress(); } @@ -5459,7 +5459,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, Address addr = Address::invalid(); RawAddress AllocaAddr = RawAddress::invalid(); if (I->isAggregate()) { - addr = I->hasLValue() ? I->getKnownLValue().getAddress(*this) + addr = I->hasLValue() ? I->getKnownLValue().getAddress() : I->getKnownRValue().getAggregateAddress(); } else { diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index b3077292f4a2..b8cb78266130 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -680,7 +680,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, // the constructor. QualType::DestructionKind dtorKind = FieldType.isDestructedType(); if (CGF.needsEHCleanup(dtorKind)) - CGF.pushEHDestroy(dtorKind, LHS.getAddress(CGF), FieldType); + CGF.pushEHDestroy(dtorKind, LHS.getAddress(), FieldType); return; } } @@ -705,9 +705,9 @@ void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS, break; case TEK_Aggregate: { AggValueSlot Slot = AggValueSlot::forLValue( - LHS, *this, AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased, - getOverlapForFieldInit(Field), AggValueSlot::IsNotZeroed, + LHS, AggValueSlot::IsDestructed, AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased, getOverlapForFieldInit(Field), + AggValueSlot::IsNotZeroed, // Checks are made by the code that calls constructor. AggValueSlot::IsSanitizerChecked); EmitAggExpr(Init, Slot); @@ -719,7 +719,7 @@ void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS, // later in the constructor. QualType::DestructionKind dtorKind = FieldType.isDestructedType(); if (needsEHCleanup(dtorKind)) - pushEHDestroy(dtorKind, LHS.getAddress(*this), FieldType); + pushEHDestroy(dtorKind, LHS.getAddress(), FieldType); } /// Checks whether the given constructor is a valid subject for the @@ -983,8 +983,8 @@ namespace { LValue Src = CGF.EmitLValueForFieldInitialization(SrcLV, FirstField); emitMemcpyIR( - Dest.isBitField() ? Dest.getBitFieldAddress() : Dest.getAddress(CGF), - Src.isBitField() ? Src.getBitFieldAddress() : Src.getAddress(CGF), + Dest.isBitField() ? Dest.getBitFieldAddress() : Dest.getAddress(), + Src.isBitField() ? Src.getBitFieldAddress() : Src.getAddress(), MemcpySize); reset(); } @@ -1131,7 +1131,7 @@ namespace { continue; LValue FieldLHS = LHS; EmitLValueForAnyFieldInitialization(CGF, MemberInit, FieldLHS); - CGF.pushEHDestroy(dtorKind, FieldLHS.getAddress(CGF), FieldType); + CGF.pushEHDestroy(dtorKind, FieldLHS.getAddress(), FieldType); } } @@ -1647,7 +1647,7 @@ namespace { LValue LV = CGF.EmitLValueForField(ThisLV, field); assert(LV.isSimple()); - CGF.emitDestroy(LV.getAddress(CGF), field->getType(), destroyer, + CGF.emitDestroy(LV.getAddress(), field->getType(), destroyer, flags.isForNormalCleanup() && useEHCleanupForArray); } }; diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 9cc67cdbe424..4a213990d1e3 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -738,18 +738,17 @@ static bool tryEmitARCCopyWeakInit(CodeGenFunction &CGF, LValue srcLV = CGF.EmitLValue(srcExpr); // Handle a formal type change to avoid asserting. - auto srcAddr = srcLV.getAddress(CGF); + auto srcAddr = srcLV.getAddress(); if (needsCast) { - srcAddr = - srcAddr.withElementType(destLV.getAddress(CGF).getElementType()); + srcAddr = srcAddr.withElementType(destLV.getAddress().getElementType()); } // If it was an l-value, use objc_copyWeak. if (srcExpr->isLValue()) { - CGF.EmitARCCopyWeak(destLV.getAddress(CGF), srcAddr); + CGF.EmitARCCopyWeak(destLV.getAddress(), srcAddr); } else { assert(srcExpr->isXValue()); - CGF.EmitARCMoveWeak(destLV.getAddress(CGF), srcAddr); + CGF.EmitARCMoveWeak(destLV.getAddress(), srcAddr); } return true; } @@ -767,7 +766,7 @@ static bool tryEmitARCCopyWeakInit(CodeGenFunction &CGF, static void drillIntoBlockVariable(CodeGenFunction &CGF, LValue &lvalue, const VarDecl *var) { - lvalue.setAddress(CGF.emitBlockByrefAddress(lvalue.getAddress(CGF), var)); + lvalue.setAddress(CGF.emitBlockByrefAddress(lvalue.getAddress(), var)); } void CodeGenFunction::EmitNullabilityCheck(LValue LHS, llvm::Value *RHS, @@ -826,18 +825,17 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D, if (capturedByInit) { // We can use a simple GEP for this because it can't have been // moved yet. - tempLV.setAddress(emitBlockByrefAddress(tempLV.getAddress(*this), + tempLV.setAddress(emitBlockByrefAddress(tempLV.getAddress(), cast(D), /*follow*/ false)); } - auto ty = - cast(tempLV.getAddress(*this).getElementType()); + auto ty = cast(tempLV.getAddress().getElementType()); llvm::Value *zero = CGM.getNullPointer(ty, tempLV.getType()); // If __weak, we want to use a barrier under certain conditions. if (lifetime == Qualifiers::OCL_Weak) - EmitARCInitWeak(tempLV.getAddress(*this), zero); + EmitARCInitWeak(tempLV.getAddress(), zero); // Otherwise just do a simple store. else @@ -880,9 +878,9 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D, if (capturedByInit) drillIntoBlockVariable(*this, lvalue, cast(D)); if (accessedByInit) - EmitARCStoreWeak(lvalue.getAddress(*this), value, /*ignored*/ true); + EmitARCStoreWeak(lvalue.getAddress(), value, /*ignored*/ true); else - EmitARCInitWeak(lvalue.getAddress(*this), value); + EmitARCInitWeak(lvalue.getAddress(), value); return; } @@ -1620,7 +1618,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { LValue Base = MakeAddrLValue(AddrSizePair.first, D.getType(), CGM.getContext().getDeclAlign(&D), AlignmentSource::Decl); - address = Base.getAddress(*this); + address = Base.getAddress(); // Push a cleanup block to emit the call to __kmpc_free_shared in the // appropriate location at the end of the scope of the @@ -2034,10 +2032,10 @@ void CodeGenFunction::EmitExprAsInit(const Expr *init, const ValueDecl *D, else if (auto *FD = dyn_cast(D)) Overlap = getOverlapForFieldInit(FD); // TODO: how can we delay here if D is captured by its initializer? - EmitAggExpr(init, AggValueSlot::forLValue( - lvalue, *this, AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, Overlap)); + EmitAggExpr(init, + AggValueSlot::forLValue(lvalue, AggValueSlot::IsDestructed, + AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased, Overlap)); } return; } @@ -2683,7 +2681,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, // objc_storeStrong attempts to release its old value. llvm::Value *Null = CGM.EmitNullConstant(D.getType()); EmitStoreOfScalar(Null, lv, /* isInitialization */ true); - EmitARCStoreStrongCall(lv.getAddress(*this), ArgVal, true); + EmitARCStoreStrongCall(lv.getAddress(), ArgVal, true); DoStore = false; } else diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index e08a1e5f42df..b047279912f6 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -57,7 +57,7 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D, return; case TEK_Aggregate: CGF.EmitAggExpr(Init, - AggValueSlot::forLValue(lv, CGF, AggValueSlot::IsDestructed, + AggValueSlot::forLValue(lv, AggValueSlot::IsDestructed, AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap)); diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 8acda3f2eb86..bb2ed237ee9f 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -1989,8 +1989,7 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, LValue ThisFieldLValue = EmitLValueForLambdaField(LambdaThisCaptureField); if (!LambdaThisCaptureField->getType()->isPointerType()) { - CXXThisValue = - ThisFieldLValue.getAddress(*this).emitRawPointer(*this); + CXXThisValue = ThisFieldLValue.getAddress().emitRawPointer(*this); } else { CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation()) .getScalarVal(); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index d96c7bb1e568..cd1c48b42038 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -605,7 +605,7 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { LV = EmitLValueForField(LV, Adjustment.Field); assert(LV.isSimple() && "materialized temporary field is not a simple lvalue"); - Object = LV.getAddress(*this); + Object = LV.getAddress(); break; } @@ -1123,7 +1123,7 @@ llvm::Value *CodeGenFunction::EmitCountedByFieldExpr( getPointerAlign(), "dre.load"); } else if (const MemberExpr *ME = dyn_cast(StructBase)) { LValue LV = EmitMemberExpr(ME); - Address Addr = LV.getAddress(*this); + Address Addr = LV.getAddress(); Res = Addr.emitRawPointer(*this); } else if (StructBase->getType()->isPointerType()) { LValueBaseInfo BaseInfo; @@ -1353,7 +1353,7 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, LValue LV = CGF.EmitLValue(UO->getSubExpr(), IsKnownNonNull); if (BaseInfo) *BaseInfo = LV.getBaseInfo(); if (TBAAInfo) *TBAAInfo = LV.getTBAAInfo(); - return LV.getAddress(CGF); + return LV.getAddress(); } } @@ -1368,7 +1368,7 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, LValue LV = CGF.EmitLValue(Call->getArg(0), IsKnownNonNull); if (BaseInfo) *BaseInfo = LV.getBaseInfo(); if (TBAAInfo) *TBAAInfo = LV.getTBAAInfo(); - return LV.getAddress(CGF); + return LV.getAddress(); } } } @@ -1590,7 +1590,7 @@ LValue CodeGenFunction::EmitLValueHelper(const Expr *E, if (LV.isSimple()) { // Defend against branches out of gnu statement expressions surrounded by // cleanups. - Address Addr = LV.getAddress(*this); + Address Addr = LV.getAddress(); llvm::Value *V = Addr.getBasePointer(); Scope.ForceCleanup({&V}); Addr.replaceBasePointer(V); @@ -1839,7 +1839,7 @@ llvm::Value *CodeGenFunction::emitScalarConstant( llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue, SourceLocation Loc) { - return EmitLoadOfScalar(lvalue.getAddress(*this), lvalue.isVolatile(), + return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(), lvalue.getType(), Loc, lvalue.getBaseInfo(), lvalue.getTBAAInfo(), lvalue.isNontemporal()); } @@ -2076,7 +2076,7 @@ static RawAddress MaybeConvertMatrixAddress(RawAddress Addr, // (VectorType). static void EmitStoreOfMatrixScalar(llvm::Value *value, LValue lvalue, bool isInit, CodeGenFunction &CGF) { - Address Addr = MaybeConvertMatrixAddress(lvalue.getAddress(CGF), CGF, + Address Addr = MaybeConvertMatrixAddress(lvalue.getAddress(), CGF, value->getType()->isVectorTy()); CGF.EmitStoreOfScalar(value, Addr, lvalue.isVolatile(), lvalue.getType(), lvalue.getBaseInfo(), lvalue.getTBAAInfo(), isInit, @@ -2146,7 +2146,7 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue, return; } - EmitStoreOfScalar(value, lvalue.getAddress(*this), lvalue.isVolatile(), + EmitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(), lvalue.getType(), lvalue.getBaseInfo(), lvalue.getTBAAInfo(), isInit, lvalue.isNontemporal()); } @@ -2156,7 +2156,7 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue, static RValue EmitLoadOfMatrixLValue(LValue LV, SourceLocation Loc, CodeGenFunction &CGF) { assert(LV.getType()->isConstantMatrixType()); - Address Addr = MaybeConvertMatrixAddress(LV.getAddress(CGF), CGF); + Address Addr = MaybeConvertMatrixAddress(LV.getAddress(), CGF); LV.setAddress(Addr); return RValue::get(CGF.EmitLoadOfScalar(LV, Loc)); } @@ -2167,18 +2167,18 @@ static RValue EmitLoadOfMatrixLValue(LValue LV, SourceLocation Loc, RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, SourceLocation Loc) { if (LV.isObjCWeak()) { // load of a __weak object. - Address AddrWeakObj = LV.getAddress(*this); + Address AddrWeakObj = LV.getAddress(); return RValue::get(CGM.getObjCRuntime().EmitObjCWeakRead(*this, AddrWeakObj)); } if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak) { // In MRC mode, we do a load+autorelease. if (!getLangOpts().ObjCAutoRefCount) { - return RValue::get(EmitARCLoadWeak(LV.getAddress(*this))); + return RValue::get(EmitARCLoadWeak(LV.getAddress())); } // In ARC mode, we load retained and then consume the value. - llvm::Value *Object = EmitARCLoadWeakRetained(LV.getAddress(*this)); + llvm::Value *Object = EmitARCLoadWeakRetained(LV.getAddress()); Object = EmitObjCConsumeObject(LV.getType(), Object); return RValue::get(Object); } @@ -2413,9 +2413,9 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, case Qualifiers::OCL_Weak: if (isInit) // Initialize and then skip the primitive store. - EmitARCInitWeak(Dst.getAddress(*this), Src.getScalarVal()); + EmitARCInitWeak(Dst.getAddress(), Src.getScalarVal()); else - EmitARCStoreWeak(Dst.getAddress(*this), Src.getScalarVal(), + EmitARCStoreWeak(Dst.getAddress(), Src.getScalarVal(), /*ignore*/ true); return; @@ -2429,7 +2429,7 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, if (Dst.isObjCWeak() && !Dst.isNonGC()) { // load of a __weak object. - Address LvalueDst = Dst.getAddress(*this); + Address LvalueDst = Dst.getAddress(); llvm::Value *src = Src.getScalarVal(); CGM.getObjCRuntime().EmitObjCWeakAssign(*this, src, LvalueDst); return; @@ -2437,7 +2437,7 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, if (Dst.isObjCStrong() && !Dst.isNonGC()) { // load of a __strong object. - Address LvalueDst = Dst.getAddress(*this); + Address LvalueDst = Dst.getAddress(); llvm::Value *src = Src.getScalarVal(); if (Dst.isObjCIvar()) { assert(Dst.getBaseIvarExp() && "BaseIvarExp is NULL"); @@ -2777,7 +2777,7 @@ CodeGenFunction::EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo, TBAAAccessInfo *PointeeTBAAInfo) { llvm::LoadInst *Load = - Builder.CreateLoad(RefLVal.getAddress(*this), RefLVal.isVolatile()); + Builder.CreateLoad(RefLVal.getAddress(), RefLVal.isVolatile()); CGM.DecorateInstructionWithTBAA(Load, RefLVal.getTBAAInfo()); return makeNaturalAddressForPointer(Load, RefLVal.getType()->getPointeeType(), CharUnits(), /*ForPointeeType=*/true, @@ -3027,7 +3027,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { LValue CapLVal = EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD), CapturedStmtInfo->getContextValue()); - Address LValueAddress = CapLVal.getAddress(*this); + Address LValueAddress = CapLVal.getAddress(); CapLVal = MakeAddrLValue(Address(LValueAddress.emitRawPointer(*this), LValueAddress.getElementType(), getContext().getDeclAlign(VD)), @@ -3217,7 +3217,7 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { // __real is valid on scalars. This is a faster way of testing that. // __imag can only produce an rvalue on scalars. if (E->getOpcode() == UO_Real && - !LV.getAddress(*this).getElementType()->isStructTy()) { + !LV.getAddress().getElementType()->isStructTy()) { assert(E->getSubExpr()->getType()->isArithmeticType()); return LV; } @@ -3226,8 +3226,8 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { Address Component = (E->getOpcode() == UO_Real - ? emitAddrOfRealComponent(LV.getAddress(*this), LV.getType()) - : emitAddrOfImagComponent(LV.getAddress(*this), LV.getType())); + ? emitAddrOfRealComponent(LV.getAddress(), LV.getType()) + : emitAddrOfImagComponent(LV.getAddress(), LV.getType())); LValue ElemLV = MakeAddrLValue(Component, T, LV.getBaseInfo(), CGM.getTBAAInfoForSubobject(LV, T)); ElemLV.getQuals().addQualifiers(LV.getQuals()); @@ -3882,7 +3882,7 @@ Address CodeGenFunction::EmitArrayToPointerDecay(const Expr *E, // Expressions of array type can't be bitfields or vector elements. LValue LV = EmitLValue(E); - Address Addr = LV.getAddress(*this); + Address Addr = LV.getAddress(); // If the array type was an incomplete type, we need to make sure // the decay ends up being the right type. @@ -4186,9 +4186,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, LValue LHS = EmitLValue(E->getBase()); auto *Idx = EmitIdxAfterBase(/*Promote*/false); assert(LHS.isSimple() && "Can only subscript lvalue vectors here!"); - return LValue::MakeVectorElt(LHS.getAddress(*this), Idx, - E->getBase()->getType(), LHS.getBaseInfo(), - TBAAAccessInfo()); + return LValue::MakeVectorElt(LHS.getAddress(), Idx, E->getBase()->getType(), + LHS.getBaseInfo(), TBAAAccessInfo()); } // All the other cases basically behave like simple offsetting. @@ -4300,7 +4299,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, // Create a GEP with a byte offset between the FAM and count and // use that to load the count value. Addr = Builder.CreatePointerBitCastOrAddrSpaceCast( - ArrayLV.getAddress(*this), Int8PtrTy, Int8Ty); + ArrayLV.getAddress(), Int8PtrTy, Int8Ty); llvm::Type *CountTy = ConvertType(CountFD->getType()); llvm::Value *Res = Builder.CreateInBoundsGEP( @@ -4320,7 +4319,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, // Propagate the alignment from the array itself to the result. QualType arrayType = Array->getType(); Addr = emitArraySubscriptGEP( - *this, ArrayLV.getAddress(*this), {CGM.getSize(CharUnits::Zero()), Idx}, + *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, E->getType(), !getLangOpts().isSignedOverflowDefined(), SignedIndices, E->getExprLoc(), &arrayType, E->getBase()); EltBaseInfo = ArrayLV.getBaseInfo(); @@ -4359,7 +4358,7 @@ LValue CodeGenFunction::EmitMatrixSubscriptExpr(const MatrixSubscriptExpr *E) { llvm::Value *FinalIdx = Builder.CreateAdd(Builder.CreateMul(ColIdx, NumRows), RowIdx); return LValue::MakeMatrixElt( - MaybeConvertMatrixAddress(Base.getAddress(*this), *this), FinalIdx, + MaybeConvertMatrixAddress(Base.getAddress(), *this), FinalIdx, E->getBase()->getType(), Base.getBaseInfo(), TBAAAccessInfo()); } @@ -4372,7 +4371,7 @@ static Address emitOMPArraySectionBase(CodeGenFunction &CGF, const Expr *Base, if (auto *ASE = dyn_cast(Base->IgnoreParenImpCasts())) { BaseLVal = CGF.EmitArraySectionExpr(ASE, IsLowerBound); if (BaseTy->isArrayType()) { - Address Addr = BaseLVal.getAddress(CGF); + Address Addr = BaseLVal.getAddress(); BaseInfo = BaseLVal.getBaseInfo(); // If the array type was an incomplete type, we need to make sure @@ -4396,7 +4395,7 @@ static Address emitOMPArraySectionBase(CodeGenFunction &CGF, const Expr *Base, CGF.CGM.getNaturalTypeAlignment(ElTy, &TypeBaseInfo, &TypeTBAAInfo); BaseInfo.mergeForCast(TypeBaseInfo); TBAAInfo = CGF.CGM.mergeTBAAInfoForCast(TBAAInfo, TypeTBAAInfo); - return Address(CGF.Builder.CreateLoad(BaseLVal.getAddress(CGF)), + return Address(CGF.Builder.CreateLoad(BaseLVal.getAddress()), CGF.ConvertTypeForMem(ElTy), Align); } return CGF.EmitPointerWithAlignment(Base, &BaseInfo, &TBAAInfo); @@ -4548,7 +4547,7 @@ LValue CodeGenFunction::EmitArraySectionExpr(const ArraySectionExpr *E, // Propagate the alignment from the array itself to the result. EltPtr = emitArraySubscriptGEP( - *this, ArrayLV.getAddress(*this), {CGM.getSize(CharUnits::Zero()), Idx}, + *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, ResultExprTy, !getLangOpts().isSignedOverflowDefined(), /*signedIndices=*/false, E->getExprLoc()); BaseInfo = ArrayLV.getBaseInfo(); @@ -4608,7 +4607,7 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { if (Base.isSimple()) { llvm::Constant *CV = llvm::ConstantDataVector::get(getLLVMContext(), Indices); - return LValue::MakeExtVectorElt(Base.getAddress(*this), CV, type, + return LValue::MakeExtVectorElt(Base.getAddress(), CV, type, Base.getBaseInfo(), TBAAAccessInfo()); } assert(Base.isExtVectorElt() && "Can only subscript lvalue vec elts here!"); @@ -4797,7 +4796,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, field->getType() .withCVRQualifiers(base.getVRQualifiers()) .isVolatileQualified(); - Address Addr = base.getAddress(*this); + Address Addr = base.getAddress(); unsigned Idx = RL.getLLVMFieldNo(field); const RecordDecl *rec = field->getParent(); if (hasBPFPreserveStaticOffset(rec)) @@ -4873,7 +4872,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, getContext().getTypeSizeInChars(FieldType).getQuantity(); } - Address addr = base.getAddress(*this); + Address addr = base.getAddress(); if (hasBPFPreserveStaticOffset(rec)) addr = wrapWithBPFPreserveStaticOffset(*this, addr); if (auto *ClassDef = dyn_cast(rec)) { @@ -4960,7 +4959,7 @@ CodeGenFunction::EmitLValueForFieldInitialization(LValue Base, if (!FieldType->isReferenceType()) return EmitLValueForField(Base, Field); - Address V = emitAddrOfFieldStorage(*this, Base.getAddress(*this), Field); + Address V = emitAddrOfFieldStorage(*this, Base.getAddress(), Field); // Make sure that the address is pointing to the right type. llvm::Type *llvmType = ConvertTypeForMem(FieldType); @@ -5142,8 +5141,8 @@ LValue CodeGenFunction::EmitConditionalOperatorLValue( return EmitUnsupportedLValue(expr, "conditional operator"); if (Info.LHS && Info.RHS) { - Address lhsAddr = Info.LHS->getAddress(*this); - Address rhsAddr = Info.RHS->getAddress(*this); + Address lhsAddr = Info.LHS->getAddress(); + Address rhsAddr = Info.RHS->getAddress(); Address result = mergeAddressesInConditionalExpr( lhsAddr, rhsAddr, Info.lhsBlock, Info.rhsBlock, Builder.GetInsertBlock(), expr->getType()); @@ -5232,7 +5231,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CK_Dynamic: { LValue LV = EmitLValue(E->getSubExpr()); - Address V = LV.getAddress(*this); + Address V = LV.getAddress(); const auto *DCE = cast(E); return MakeNaturalAlignRawAddrLValue(EmitDynamicCast(V, DCE), E->getType()); } @@ -5253,7 +5252,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { if (E->changesVolatileQualification()) LV.getQuals() = E->getType().getQualifiers(); if (LV.isSimple()) { - Address V = LV.getAddress(*this); + Address V = LV.getAddress(); if (V.isValid()) { llvm::Type *T = ConvertTypeForMem(E->getType()); if (V.getElementType() != T) @@ -5270,7 +5269,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { auto *DerivedClassDecl = cast(DerivedClassTy->getDecl()); LValue LV = EmitLValue(E->getSubExpr()); - Address This = LV.getAddress(*this); + Address This = LV.getAddress(); // Perform the derived-to-base conversion Address Base = GetAddressOfBaseClass( @@ -5293,7 +5292,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { // Perform the base-to-derived conversion Address Derived = GetAddressOfDerivedClass( - LV.getAddress(*this), DerivedClassDecl, E->path_begin(), E->path_end(), + LV.getAddress(), DerivedClassDecl, E->path_begin(), E->path_end(), /*NullCheckValue=*/false); // C++11 [expr.static.cast]p2: Behavior is undefined if a downcast is @@ -5316,7 +5315,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { CGM.EmitExplicitCastExprType(CE, this); LValue LV = EmitLValue(E->getSubExpr()); - Address V = LV.getAddress(*this).withElementType( + Address V = LV.getAddress().withElementType( ConvertTypeForMem(CE->getTypeAsWritten()->getPointeeType())); if (SanOpts.has(SanitizerKind::CFIUnrelatedCast)) @@ -5335,12 +5334,12 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { E->getSubExpr()->getType().getAddressSpace(), E->getType().getAddressSpace(), ConvertType(DestTy)); return MakeAddrLValue(Address(V, ConvertTypeForMem(E->getType()), - LV.getAddress(*this).getAlignment()), + LV.getAddress().getAlignment()), E->getType(), LV.getBaseInfo(), LV.getTBAAInfo()); } case CK_ObjCObjectLValueCast: { LValue LV = EmitLValue(E->getSubExpr()); - Address V = LV.getAddress(*this).withElementType(ConvertType(E->getType())); + Address V = LV.getAddress().withElementType(ConvertType(E->getType())); return MakeAddrLValue(V, E->getType(), LV.getBaseInfo(), CGM.getTBAAInfoForSubobject(LV, E->getType())); } @@ -5400,7 +5399,7 @@ RValue CodeGenFunction::EmitRValueForField(LValue LV, case TEK_Complex: return RValue::getComplex(EmitLoadOfComplex(FieldLV, Loc)); case TEK_Aggregate: - return FieldLV.asAggregateRValue(*this); + return FieldLV.asAggregateRValue(); case TEK_Scalar: // This routine is used to load fields one-by-one to perform a copy, so // don't load reference fields. @@ -6022,7 +6021,7 @@ EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) { if (E->getOpcode() == BO_PtrMemI) { BaseAddr = EmitPointerWithAlignment(E->getLHS()); } else { - BaseAddr = EmitLValue(E->getLHS()).getAddress(*this); + BaseAddr = EmitLValue(E->getLHS()).getAddress(); } llvm::Value *OffsetV = EmitScalarExpr(E->getRHS()); @@ -6047,7 +6046,7 @@ RValue CodeGenFunction::convertTempToRValue(Address addr, case TEK_Complex: return RValue::getComplex(EmitLoadOfComplex(lvalue, loc)); case TEK_Aggregate: - return lvalue.asAggregateRValue(*this); + return lvalue.asAggregateRValue(); case TEK_Scalar: return RValue::get(EmitLoadOfScalar(lvalue, loc)); } diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 6172eb9cdc1b..bba00257fd4f 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -384,8 +384,8 @@ void AggExprEmitter::EmitFinalDestCopy(QualType type, const LValue &src, } AggValueSlot srcAgg = AggValueSlot::forLValue( - src, CGF, AggValueSlot::IsDestructed, needsGC(type), - AggValueSlot::IsAliased, AggValueSlot::MayOverlap); + src, AggValueSlot::IsDestructed, needsGC(type), AggValueSlot::IsAliased, + AggValueSlot::MayOverlap); EmitCopy(type, Dest, srcAgg); } @@ -423,7 +423,7 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { ASTContext &Ctx = CGF.getContext(); LValue Array = CGF.EmitLValue(E->getSubExpr()); assert(Array.isSimple() && "initializer_list array not a simple lvalue"); - Address ArrayPtr = Array.getAddress(CGF); + Address ArrayPtr = Array.getAddress(); const ConstantArrayType *ArrayType = Ctx.getAsConstantArrayType(E->getSubExpr()->getType()); @@ -747,7 +747,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { CodeGenFunction::TCK_Load); // FIXME: Do we also need to handle property references here? if (LV.isSimple()) - CGF.EmitDynamicCast(LV.getAddress(CGF), cast(E)); + CGF.EmitDynamicCast(LV.getAddress(), cast(E)); else CGF.CGM.ErrorUnsupported(E, "non-simple lvalue dynamic_cast"); @@ -780,8 +780,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { } LValue SourceLV = CGF.EmitLValue(E->getSubExpr()); - Address SourceAddress = - SourceLV.getAddress(CGF).withElementType(CGF.Int8Ty); + Address SourceAddress = SourceLV.getAddress().withElementType(CGF.Int8Ty); Address DestAddress = Dest.getAddress().withElementType(CGF.Int8Ty); llvm::Value *SizeVal = llvm::ConstantInt::get( CGF.SizeTy, @@ -1231,7 +1230,7 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { } EmitCopy(E->getLHS()->getType(), - AggValueSlot::forLValue(LHS, CGF, AggValueSlot::IsDestructed, + AggValueSlot::forLValue(LHS, AggValueSlot::IsDestructed, needsGC(E->getLHS()->getType()), AggValueSlot::IsAliased, AggValueSlot::MayOverlap), @@ -1253,7 +1252,7 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { // Codegen the RHS so that it stores directly into the LHS. AggValueSlot LHSSlot = AggValueSlot::forLValue( - LHS, CGF, AggValueSlot::IsDestructed, needsGC(E->getLHS()->getType()), + LHS, AggValueSlot::IsDestructed, needsGC(E->getLHS()->getType()), AggValueSlot::IsAliased, AggValueSlot::MayOverlap); // A non-volatile aggregate destination might have volatile member. if (!LHSSlot.isVolatile() && @@ -1400,9 +1399,9 @@ AggExprEmitter::VisitLambdaExpr(LambdaExpr *E) { CurField->getType().isDestructedType()) { assert(LV.isSimple()); if (DtorKind) - CGF.pushDestroyAndDeferDeactivation( - NormalAndEHCleanup, LV.getAddress(CGF), CurField->getType(), - CGF.getDestroyer(DtorKind), false); + CGF.pushDestroyAndDeferDeactivation(NormalAndEHCleanup, LV.getAddress(), + CurField->getType(), + CGF.getDestroyer(DtorKind), false); } } } @@ -1580,7 +1579,7 @@ AggExprEmitter::EmitInitializationToLValue(Expr *E, LValue LV) { return; case TEK_Aggregate: CGF.EmitAggExpr( - E, AggValueSlot::forLValue(LV, CGF, AggValueSlot::IsDestructed, + E, AggValueSlot::forLValue(LV, AggValueSlot::IsDestructed, AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased, AggValueSlot::MayOverlap, Dest.isZeroed())); @@ -1619,7 +1618,7 @@ void AggExprEmitter::EmitNullInitializationToLValue(LValue lv) { // There's a potential optimization opportunity in combining // memsets; that would be easy for arrays, but relatively // difficult for structures with the current code. - CGF.EmitNullInitialization(lv.getAddress(CGF), lv.getType()); + CGF.EmitNullInitialization(lv.getAddress(), lv.getType()); } } @@ -1795,9 +1794,9 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr( = field->getType().isDestructedType()) { assert(LV.isSimple()); if (dtorKind) { - CGF.pushDestroyAndDeferDeactivation( - NormalAndEHCleanup, LV.getAddress(CGF), field->getType(), - CGF.getDestroyer(dtorKind), false); + CGF.pushDestroyAndDeferDeactivation(NormalAndEHCleanup, LV.getAddress(), + field->getType(), + CGF.getDestroyer(dtorKind), false); pushedCleanup = true; } } @@ -1880,7 +1879,7 @@ void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E, if (InnerLoop) { // If the subexpression is an ArrayInitLoopExpr, share its cleanup. auto elementSlot = AggValueSlot::forLValue( - elementLV, CGF, AggValueSlot::IsDestructed, + elementLV, AggValueSlot::IsDestructed, AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap); AggExprEmitter(CGF, elementSlot, false) @@ -2045,10 +2044,10 @@ LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) { assert(hasAggregateEvaluationKind(E->getType()) && "Invalid argument!"); Address Temp = CreateMemTemp(E->getType()); LValue LV = MakeAddrLValue(Temp, E->getType()); - EmitAggExpr(E, AggValueSlot::forLValue( - LV, *this, AggValueSlot::IsNotDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap)); + EmitAggExpr(E, AggValueSlot::forLValue(LV, AggValueSlot::IsNotDestructed, + AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased, + AggValueSlot::DoesNotOverlap)); return LV; } @@ -2097,8 +2096,8 @@ void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src, QualType Ty, bool isVolatile) { assert(!Ty->isAnyComplexType() && "Shouldn't happen for complex"); - Address DestPtr = Dest.getAddress(*this); - Address SrcPtr = Src.getAddress(*this); + Address DestPtr = Dest.getAddress(); + Address SrcPtr = Src.getAddress(); if (getLangOpts().CPlusPlus) { if (const RecordType *RT = Ty->getAs()) { diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 0cfdb7effe47..3c4f59fc765f 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -142,7 +142,7 @@ RValue CodeGenFunction::EmitCXXPseudoDestructorExpr( BaseQuals = PTy->getPointeeType().getQualifiers(); } else { LValue BaseLV = EmitLValue(BaseExpr); - BaseValue = BaseLV.getAddress(*this); + BaseValue = BaseLV.getAddress(); QualType BaseTy = BaseExpr->getType(); BaseQuals = BaseTy.getQualifiers(); } @@ -298,7 +298,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( /*ImplicitParamTy=*/QualType(), CE, Args, nullptr); EmitCXXConstructorCall(Ctor, Ctor_Complete, /*ForVirtualBase=*/false, - /*Delegating=*/false, This.getAddress(*this), Args, + /*Delegating=*/false, This.getAddress(), Args, AggValueSlot::DoesNotOverlap, CE->getExprLoc(), /*NewPointerIsChecked=*/false); return RValue::get(nullptr); @@ -375,7 +375,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( assert(ReturnValue.isNull() && "Destructor shouldn't have return value"); if (UseVirtualCall) { CGM.getCXXABI().EmitVirtualDestructorCall(*this, Dtor, Dtor_Complete, - This.getAddress(*this), + This.getAddress(), cast(CE)); } else { GlobalDecl GD(Dtor, Dtor_Complete); @@ -403,14 +403,14 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( CGCallee Callee; if (UseVirtualCall) { - Callee = CGCallee::forVirtual(CE, MD, This.getAddress(*this), Ty); + Callee = CGCallee::forVirtual(CE, MD, This.getAddress(), Ty); } else { if (SanOpts.has(SanitizerKind::CFINVCall) && MD->getParent()->isDynamicClass()) { llvm::Value *VTable; const CXXRecordDecl *RD; std::tie(VTable, RD) = CGM.getCXXABI().LoadVTablePtr( - *this, This.getAddress(*this), CalleeDecl->getParent()); + *this, This.getAddress(), CalleeDecl->getParent()); EmitVTablePtrCheckForCall(RD, VTable, CFITCK_NVCall, CE->getBeginLoc()); } @@ -429,7 +429,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( if (MD->isVirtual()) { Address NewThisAddr = CGM.getCXXABI().adjustThisArgumentForVirtualFunctionCall( - *this, CalleeDecl, This.getAddress(*this), UseVirtualCall); + *this, CalleeDecl, This.getAddress(), UseVirtualCall); This.setAddress(NewThisAddr); } @@ -456,7 +456,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, if (BO->getOpcode() == BO_PtrMemI) This = EmitPointerWithAlignment(BaseExpr, nullptr, nullptr, KnownNonNull); else - This = EmitLValue(BaseExpr, KnownNonNull).getAddress(*this); + This = EmitLValue(BaseExpr, KnownNonNull).getAddress(); EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.emitRawPointer(*this), QualType(MPT->getClass(), 0)); @@ -2178,7 +2178,7 @@ static bool isGLValueFromPointerDeref(const Expr *E) { static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E, llvm::Type *StdTypeInfoPtrTy) { // Get the vtable pointer. - Address ThisPtr = CGF.EmitLValue(E).getAddress(CGF); + Address ThisPtr = CGF.EmitLValue(E).getAddress(); QualType SrcRecordTy = E->getType(); diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 1facadd82f17..9ef73e36f66f 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -434,7 +434,7 @@ ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue, if (lvalue.getType()->isAtomicType()) return CGF.EmitAtomicLoad(lvalue, loc).getComplexVal(); - Address SrcPtr = lvalue.getAddress(CGF); + Address SrcPtr = lvalue.getAddress(); bool isVolatile = lvalue.isVolatileQualified(); llvm::Value *Real = nullptr, *Imag = nullptr; @@ -460,7 +460,7 @@ void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, LValue lvalue, (!isInit && CGF.LValueIsSuitableForInlineAtomic(lvalue))) return CGF.EmitAtomicStore(RValue::getComplex(Val), lvalue, isInit); - Address Ptr = lvalue.getAddress(CGF); + Address Ptr = lvalue.getAddress(); Address RealPtr = CGF.emitAddrOfRealComponent(Ptr, lvalue.getType()); Address ImagPtr = CGF.emitAddrOfImagComponent(Ptr, lvalue.getType()); @@ -551,14 +551,14 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op, case CK_LValueBitCast: { LValue origLV = CGF.EmitLValue(Op); - Address V = origLV.getAddress(CGF).withElementType(CGF.ConvertType(DestTy)); + Address V = origLV.getAddress().withElementType(CGF.ConvertType(DestTy)); return EmitLoadOfLValue(CGF.MakeAddrLValue(V, DestTy), Op->getExprLoc()); } case CK_LValueToRValueBitCast: { LValue SourceLVal = CGF.EmitLValue(Op); - Address Addr = SourceLVal.getAddress(CGF).withElementType( - CGF.ConvertTypeForMem(DestTy)); + Address Addr = + SourceLVal.getAddress().withElementType(CGF.ConvertTypeForMem(DestTy)); LValue DestLV = CGF.MakeAddrLValue(Addr, DestTy); DestLV.setTBAAInfo(TBAAAccessInfo::getMayAliasInfo()); return EmitLoadOfLValue(DestLV, Op->getExprLoc()); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index d84531959b50..1b144c178ce9 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2212,7 +2212,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { case CK_LValueBitCast: case CK_ObjCObjectLValueCast: { - Address Addr = EmitLValue(E).getAddress(CGF); + Address Addr = EmitLValue(E).getAddress(); Addr = Addr.withElementType(CGF.ConvertTypeForMem(DestTy)); LValue LV = CGF.MakeAddrLValue(Addr, DestTy); return EmitLoadOfLValue(LV, CE->getExprLoc()); @@ -2220,8 +2220,8 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { case CK_LValueToRValueBitCast: { LValue SourceLVal = CGF.EmitLValue(E); - Address Addr = SourceLVal.getAddress(CGF).withElementType( - CGF.ConvertTypeForMem(DestTy)); + Address Addr = + SourceLVal.getAddress().withElementType(CGF.ConvertTypeForMem(DestTy)); LValue DestLV = CGF.MakeAddrLValue(Addr, DestTy); DestLV.setTBAAInfo(TBAAAccessInfo::getMayAliasInfo()); return EmitLoadOfLValue(DestLV, CE->getExprLoc()); @@ -2772,14 +2772,14 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, if (isInc && type->isBooleanType()) { llvm::Value *True = CGF.EmitToMemory(Builder.getTrue(), type); if (isPre) { - Builder.CreateStore(True, LV.getAddress(CGF), LV.isVolatileQualified()) + Builder.CreateStore(True, LV.getAddress(), LV.isVolatileQualified()) ->setAtomic(llvm::AtomicOrdering::SequentiallyConsistent); return Builder.getTrue(); } // For atomic bool increment, we just store true and return it for // preincrement, do an atomic swap with true for postincrement return Builder.CreateAtomicRMW( - llvm::AtomicRMWInst::Xchg, LV.getAddress(CGF), True, + llvm::AtomicRMWInst::Xchg, LV.getAddress(), True, llvm::AtomicOrdering::SequentiallyConsistent); } // Special case for atomic increment / decrement on integers, emit @@ -2797,7 +2797,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, llvm::Value *amt = CGF.EmitToMemory( llvm::ConstantInt::get(ConvertType(type), 1, true), type); llvm::Value *old = - Builder.CreateAtomicRMW(aop, LV.getAddress(CGF), amt, + Builder.CreateAtomicRMW(aop, LV.getAddress(), amt, llvm::AtomicOrdering::SequentiallyConsistent); return isPre ? Builder.CreateBinOp(op, old, amt) : old; } @@ -2810,7 +2810,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, llvm::Value *amt = llvm::ConstantFP::get( VMContext, llvm::APFloat(static_cast(1.0))); llvm::Value *old = - Builder.CreateAtomicRMW(aop, LV.getAddress(CGF), amt, + Builder.CreateAtomicRMW(aop, LV.getAddress(), amt, llvm::AtomicOrdering::SequentiallyConsistent); return isPre ? Builder.CreateBinOp(op, old, amt) : old; } @@ -3552,7 +3552,7 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue( E->getExprLoc()), LHSTy); Value *OldVal = Builder.CreateAtomicRMW( - AtomicOp, LHSLV.getAddress(CGF), Amt, + AtomicOp, LHSLV.getAddress(), Amt, llvm::AtomicOrdering::SequentiallyConsistent); // Since operation is atomic, the result type is guaranteed to be the @@ -4782,7 +4782,7 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) { case Qualifiers::OCL_Weak: RHS = Visit(E->getRHS()); LHS = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store); - RHS = CGF.EmitARCStoreWeak(LHS.getAddress(CGF), RHS, Ignore); + RHS = CGF.EmitARCStoreWeak(LHS.getAddress(), RHS, Ignore); break; case Qualifiers::OCL_None: @@ -5534,7 +5534,7 @@ LValue CodeGenFunction::EmitObjCIsaExpr(const ObjCIsaExpr *E) { ConvertTypeForMem(BaseExpr->getType()->getPointeeType()); Addr = Address(EmitScalarExpr(BaseExpr), BaseTy, getPointerAlign()); } else { - Addr = EmitLValue(BaseExpr).getAddress(*this); + Addr = EmitLValue(BaseExpr).getAddress(); } // Cast the address to Class*. diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/clang/lib/CodeGen/CGNonTrivialStruct.cpp index 8fade0fac21e..6a02e4dbf84d 100644 --- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp +++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp @@ -711,7 +711,7 @@ struct GenMoveConstructor : GenBinaryFunc { LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT); llvm::Value *SrcVal = CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal(); - CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV); + CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress()), SrcLV); CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT), /* isInitialization */ true); } @@ -774,7 +774,7 @@ struct GenMoveAssignment : GenBinaryFunc { LValue SrcLV = CGF->MakeAddrLValue(Addrs[SrcIdx], QT); llvm::Value *SrcVal = CGF->EmitLoadOfLValue(SrcLV, SourceLocation()).getScalarVal(); - CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress(*CGF)), SrcLV); + CGF->EmitStoreOfScalar(getNullForVariable(SrcLV.getAddress()), SrcLV); LValue DstLV = CGF->MakeAddrLValue(Addrs[DstIdx], QT); llvm::Value *DstVal = CGF->EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal(); @@ -810,7 +810,7 @@ void CodeGenFunction::destroyNonTrivialCStruct(CodeGenFunction &CGF, // such structure. void CodeGenFunction::defaultInitNonTrivialCStructVar(LValue Dst) { GenDefaultInitialize Gen(getContext()); - Address DstPtr = Dst.getAddress(*this).withElementType(CGM.Int8PtrTy); + Address DstPtr = Dst.getAddress().withElementType(CGM.Int8PtrTy); Gen.setCGF(this); QualType QT = Dst.getType(); QT = Dst.isVolatile() ? QT.withVolatile() : QT; @@ -842,7 +842,7 @@ getSpecialFunction(G &&Gen, StringRef FuncName, QualType QT, bool IsVolatile, // Functions to emit calls to the special functions of a non-trivial C struct. void CodeGenFunction::callCStructDefaultConstructor(LValue Dst) { bool IsVolatile = Dst.isVolatile(); - Address DstPtr = Dst.getAddress(*this); + Address DstPtr = Dst.getAddress(); QualType QT = Dst.getType(); GenDefaultInitializeFuncName GenName(DstPtr.getAlignment(), getContext()); std::string FuncName = GenName.getName(QT, IsVolatile); @@ -866,7 +866,7 @@ std::string CodeGenFunction::getNonTrivialDestructorStr(QualType QT, void CodeGenFunction::callCStructDestructor(LValue Dst) { bool IsVolatile = Dst.isVolatile(); - Address DstPtr = Dst.getAddress(*this); + Address DstPtr = Dst.getAddress(); QualType QT = Dst.getType(); GenDestructorFuncName GenName("__destructor_", DstPtr.getAlignment(), getContext()); @@ -877,7 +877,7 @@ void CodeGenFunction::callCStructDestructor(LValue Dst) { void CodeGenFunction::callCStructCopyConstructor(LValue Dst, LValue Src) { bool IsVolatile = Dst.isVolatile() || Src.isVolatile(); - Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this); + Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress(); QualType QT = Dst.getType(); GenBinaryFuncName GenName("__copy_constructor_", DstPtr.getAlignment(), SrcPtr.getAlignment(), getContext()); @@ -891,7 +891,7 @@ void CodeGenFunction::callCStructCopyAssignmentOperator(LValue Dst, LValue Src ) { bool IsVolatile = Dst.isVolatile() || Src.isVolatile(); - Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this); + Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress(); QualType QT = Dst.getType(); GenBinaryFuncName GenName("__copy_assignment_", DstPtr.getAlignment(), SrcPtr.getAlignment(), getContext()); @@ -902,7 +902,7 @@ void CodeGenFunction::callCStructCopyAssignmentOperator(LValue Dst, LValue Src void CodeGenFunction::callCStructMoveConstructor(LValue Dst, LValue Src) { bool IsVolatile = Dst.isVolatile() || Src.isVolatile(); - Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this); + Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress(); QualType QT = Dst.getType(); GenBinaryFuncName GenName("__move_constructor_", DstPtr.getAlignment(), SrcPtr.getAlignment(), getContext()); @@ -916,7 +916,7 @@ void CodeGenFunction::callCStructMoveAssignmentOperator(LValue Dst, LValue Src ) { bool IsVolatile = Dst.isVolatile() || Src.isVolatile(); - Address DstPtr = Dst.getAddress(*this), SrcPtr = Src.getAddress(*this); + Address DstPtr = Dst.getAddress(), SrcPtr = Src.getAddress(); QualType QT = Dst.getType(); GenBinaryFuncName GenName("__move_assignment_", DstPtr.getAlignment(), SrcPtr.getAlignment(), getContext()); diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index ee571995ce4c..281b2d9795f6 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -586,7 +586,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E, method->getMethodFamily() == OMF_retain) { if (auto lvalueExpr = findWeakLValue(E->getInstanceReceiver())) { LValue lvalue = EmitLValue(lvalueExpr); - llvm::Value *result = EmitARCLoadWeakRetained(lvalue.getAddress(*this)); + llvm::Value *result = EmitARCLoadWeakRetained(lvalue.getAddress()); return AdjustObjCObjectType(*this, E->getType(), RValue::get(result)); } } @@ -1189,7 +1189,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, llvm::Type *bitcastType = llvm::Type::getIntNTy(getLLVMContext(), ivarSize); // Perform an atomic load. This does not impose ordering constraints. - Address ivarAddr = LV.getAddress(*this); + Address ivarAddr = LV.getAddress(); ivarAddr = ivarAddr.withElementType(bitcastType); llvm::LoadInst *load = Builder.CreateLoad(ivarAddr, "load"); load->setAtomic(llvm::AtomicOrdering::Unordered); @@ -1287,14 +1287,14 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, case TEK_Scalar: { llvm::Value *value; if (propType->isReferenceType()) { - value = LV.getAddress(*this).emitRawPointer(*this); + value = LV.getAddress().emitRawPointer(*this); } else { // We want to load and autoreleaseReturnValue ARC __weak ivars. if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak) { if (getLangOpts().ObjCAutoRefCount) { value = emitARCRetainLoadOfScalar(*this, LV, ivarType); } else { - value = EmitARCLoadWeak(LV.getAddress(*this)); + value = EmitARCLoadWeak(LV.getAddress()); } // Otherwise we want to do a simple load, suppressing the @@ -1477,7 +1477,7 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, LValue ivarLValue = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), ivar, /*quals*/ 0); - Address ivarAddr = ivarLValue.getAddress(*this); + Address ivarAddr = ivarLValue.getAddress(); // Currently, all atomic accesses have to be through integer // types, so there's no point in trying to pick a prettier type. @@ -1655,7 +1655,7 @@ namespace { void Emit(CodeGenFunction &CGF, Flags flags) override { LValue lvalue = CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), addr, ivar, /*CVR*/ 0); - CGF.emitDestroy(lvalue.getAddress(CGF), ivar->getType(), destroyer, + CGF.emitDestroy(lvalue.getAddress(), ivar->getType(), destroyer, flags.isForNormalCleanup() && useEHCleanupForArray); } }; @@ -1722,7 +1722,7 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0); EmitAggExpr(IvarInit->getInit(), - AggValueSlot::forLValue(LV, *this, AggValueSlot::IsDestructed, + AggValueSlot::forLValue(LV, AggValueSlot::IsDestructed, AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap)); @@ -2508,7 +2508,7 @@ llvm::Value *CodeGenFunction::EmitARCStoreStrong(LValue dst, !isBlock && (dst.getAlignment().isZero() || dst.getAlignment() >= CharUnits::fromQuantity(PointerAlignInBytes))) { - return EmitARCStoreStrongCall(dst.getAddress(*this), newValue, ignored); + return EmitARCStoreStrongCall(dst.getAddress(), newValue, ignored); } // Otherwise, split it out. @@ -2898,7 +2898,7 @@ static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF, result = CGF.EmitLoadOfLValue(lvalue, SourceLocation()).getScalarVal(); } else { assert(type.getObjCLifetime() == Qualifiers::OCL_Weak); - result = CGF.EmitARCLoadWeakRetained(lvalue.getAddress(CGF)); + result = CGF.EmitARCLoadWeakRetained(lvalue.getAddress()); } return TryEmitResult(result, !shouldRetain); } @@ -2922,7 +2922,7 @@ static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF, SourceLocation()).getScalarVal(); // Set the source pointer to NULL. - CGF.EmitStoreOfScalar(getNullForVariable(lv.getAddress(CGF)), lv); + CGF.EmitStoreOfScalar(getNullForVariable(lv.getAddress()), lv); return TryEmitResult(result, true); } diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index f56af318ff6a..f6d12d46cfc0 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -373,7 +373,7 @@ public: /*RefersToEnclosingVariableOrCapture=*/false, VD->getType().getNonReferenceType(), VK_LValue, C.getLocation()); - PrivScope.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress(CGF)); + PrivScope.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress()); } (void)PrivScope.Privatize(); } @@ -809,7 +809,7 @@ void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { } llvm::Value *Size; llvm::Value *SizeInChars; - auto *ElemType = OrigAddresses[N].first.getAddress(CGF).getElementType(); + auto *ElemType = OrigAddresses[N].first.getAddress().getElementType(); auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); if (AsArraySection) { Size = CGF.Builder.CreatePtrDiff(ElemType, @@ -897,15 +897,15 @@ static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && !CGF.getContext().hasSameType(BaseTy, ElTy)) { if (const auto *PtrTy = BaseTy->getAs()) { - BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); + BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy); } else { - LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); + LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(), BaseTy); BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); } BaseTy = BaseTy->getPointeeType(); } return CGF.MakeAddrLValue( - BaseLV.getAddress(CGF).withElementType(CGF.ConvertTypeForMem(ElTy)), + BaseLV.getAddress().withElementType(CGF.ConvertTypeForMem(ElTy)), BaseLV.getType(), BaseLV.getBaseInfo(), CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); } @@ -968,7 +968,7 @@ Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, LValue BaseLValue = loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), OriginalBaseLValue); - Address SharedAddr = SharedAddresses[N].first.getAddress(CGF); + Address SharedAddr = SharedAddresses[N].first.getAddress(); llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( SharedAddr.getElementType(), BaseLValue.getPointer(CGF), SharedAddr.emitRawPointer(CGF)); @@ -979,7 +979,7 @@ Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, SharedAddr.getElementType(), PrivatePointer, Adjustment); return castToBase(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), - OriginalBaseLValue.getAddress(CGF), Ptr); + OriginalBaseLValue.getAddress(), Ptr); } BaseDecls.emplace_back( cast(cast(ClausesData[N].Ref)->getDecl())); @@ -1108,11 +1108,11 @@ emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); Scope.addPrivate( In, CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs()) - .getAddress(CGF)); + .getAddress()); Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); Scope.addPrivate( Out, CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs()) - .getAddress(CGF)); + .getAddress()); (void)Scope.Privatize(); if (!IsCombiner && Out->hasInit() && !CGF.isTrivialInitializer(Out->getInit())) { @@ -1946,7 +1946,7 @@ Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, if (auto *OMPRegionInfo = dyn_cast_or_null(CGF.CapturedStmtInfo)) if (OMPRegionInfo->getThreadIDVariable()) - return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); + return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(); llvm::Value *ThreadID = getThreadID(CGF, Loc); QualType Int32Ty = @@ -3046,7 +3046,7 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, llvm::Value *CommonArgs[] = { GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap, CGF.Builder - .CreatePointerBitCastOrAddrSpaceCast(TDBase.getAddress(CGF), + .CreatePointerBitCastOrAddrSpaceCast(TDBase.getAddress(), CGF.VoidPtrTy, CGF.Int8Ty) .emitRawPointer(CGF)}; SmallVector CallArgs(std::begin(CommonArgs), @@ -3125,7 +3125,7 @@ static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, if (QualType::DestructionKind DtorKind = Field->getType().isDestructedType()) { LValue FieldLValue = CGF.EmitLValueForField(Base, Field); - CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); + CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType()); } } CGF.FinishFunction(); @@ -3233,7 +3233,7 @@ emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, LValue RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( - RefLVal.getAddress(CGF), RefLVal.getType()->castAs()); + RefLVal.getAddress(), RefLVal.getType()->castAs()); CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); ++Counter; } @@ -3305,7 +3305,7 @@ static void emitPrivatesInit(CodeGenFunction &CGF, } else if (ForDup) { SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); SharedRefLValue = CGF.MakeAddrLValue( - SharedRefLValue.getAddress(CGF).withAlignment( + SharedRefLValue.getAddress().withAlignment( C.getDeclAlign(OriginalVD)), SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), SharedRefLValue.getTBAAInfo()); @@ -3329,8 +3329,7 @@ static void emitPrivatesInit(CodeGenFunction &CGF, // Initialize firstprivate array using element-by-element // initialization. CGF.EmitOMPAggregateAssign( - PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), - Type, + PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type, [&CGF, Elem, Init, &CapturesInfo](Address DestElement, Address SrcElement) { // Clean up any temporaries needed by the initialization. @@ -3347,7 +3346,7 @@ static void emitPrivatesInit(CodeGenFunction &CGF, } } else { CodeGenFunction::OMPPrivateScope InitScope(CGF); - InitScope.addPrivate(Elem, SharedRefLValue.getAddress(CGF)); + InitScope.addPrivate(Elem, SharedRefLValue.getAddress()); (void)InitScope.Privatize(); CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); CGF.EmitExprAsInit(Init, VD, PrivateLValue, @@ -3508,7 +3507,7 @@ public: HelperData.CounterVD->getType()); // Counter = 0; CGF.EmitStoreOfScalar( - llvm::ConstantInt::get(CLVal.getAddress(CGF).getElementType(), 0), + llvm::ConstantInt::get(CLVal.getAddress().getElementType(), 0), CLVal); CodeGenFunction::JumpDest &ContDest = ContDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.cont")); @@ -3572,7 +3571,7 @@ getPointerAndSize(CodeGenFunction &CGF, const Expr *E) { } else if (const auto *ASE = dyn_cast(E->IgnoreParenImpCasts())) { LValue UpAddrLVal = CGF.EmitArraySectionExpr(ASE, /*IsLowerBound=*/false); - Address UpAddrAddress = UpAddrLVal.getAddress(CGF); + Address UpAddrAddress = UpAddrLVal.getAddress(); llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( UpAddrAddress.getElementType(), UpAddrAddress.emitRawPointer(CGF), /*Idx0=*/1); @@ -4045,11 +4044,11 @@ CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, cast(KmpDependInfoTy->getAsTagDecl()); QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); LValue Base = CGF.EmitLoadOfPointerLValue( - DepobjLVal.getAddress(CGF).withElementType( + DepobjLVal.getAddress().withElementType( CGF.ConvertTypeForMem(KmpDependInfoPtrTy)), KmpDependInfoPtrTy->castAs()); Address DepObjAddr = CGF.Builder.CreateGEP( - CGF, Base.getAddress(CGF), + CGF, Base.getAddress(), llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); LValue NumDepsBase = CGF.MakeAddrLValue( DepObjAddr, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo()); @@ -4156,7 +4155,7 @@ SmallVector CGOpenMPRuntime::emitDepobjElementsSizes( CGF.CreateMemTemp(C.getUIntPtrType(), "depobj.size.addr"), C.getUIntPtrType()); CGF.Builder.CreateStore(llvm::ConstantInt::get(CGF.IntPtrTy, 0), - NumLVal.getAddress(CGF)); + NumLVal.getAddress()); llvm::Value *PrevVal = CGF.EmitLoadOfScalar(NumLVal, E->getExprLoc()); llvm::Value *Add = CGF.Builder.CreateNUWAdd(PrevVal, NumDeps); CGF.EmitStoreOfScalar(Add, NumLVal); @@ -4198,7 +4197,7 @@ void CGOpenMPRuntime::emitDepobjElements(CodeGenFunction &CGF, CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false)); llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); Address DepAddr = CGF.Builder.CreateGEP(CGF, DependenciesArray, Pos); - CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size); + CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(), Size); // Increase pos. // pos += size; @@ -4425,11 +4424,11 @@ void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, ASTContext &C = CGM.getContext(); QualType FlagsTy; getDependTypes(C, KmpDependInfoTy, FlagsTy); - LValue Base = CGF.EmitLoadOfPointerLValue( - DepobjLVal.getAddress(CGF), C.VoidPtrTy.castAs()); + LValue Base = CGF.EmitLoadOfPointerLValue(DepobjLVal.getAddress(), + C.VoidPtrTy.castAs()); QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy), + Base.getAddress(), CGF.ConvertTypeForMem(KmpDependInfoPtrTy), CGF.ConvertTypeForMem(KmpDependInfoTy)); llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( Addr.getElementType(), Addr.emitRawPointer(CGF), @@ -4460,7 +4459,7 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, LValue Base; std::tie(NumDeps, Base) = getDepobjElements(CGF, DepobjLVal, Loc); - Address Begin = Base.getAddress(CGF); + Address Begin = Base.getAddress(); // Cast from pointer to array type to pointer to single element. llvm::Value *End = CGF.Builder.CreateGEP(Begin.getElementType(), Begin.emitRawPointer(CGF), NumDeps); @@ -4646,24 +4645,21 @@ void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); const auto *LBVar = cast(cast(D.getLowerBoundVariable())->getDecl()); - CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), - LBLVal.getQuals(), + CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(), /*IsInitializer=*/true); LValue UBLVal = CGF.EmitLValueForField( Result.TDBase, *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); const auto *UBVar = cast(cast(D.getUpperBoundVariable())->getDecl()); - CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), - UBLVal.getQuals(), + CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(), /*IsInitializer=*/true); LValue StLVal = CGF.EmitLValueForField( Result.TDBase, *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); const auto *StVar = cast(cast(D.getStrideVariable())->getDecl()); - CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), - StLVal.getQuals(), + CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(), /*IsInitializer=*/true); // Store reductions address. LValue RedLVal = CGF.EmitLValueForField( @@ -4672,7 +4668,7 @@ void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, if (Data.Reductions) { CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); } else { - CGF.EmitNullInitialization(RedLVal.getAddress(CGF), + CGF.EmitNullInitialization(RedLVal.getAddress(), CGF.getContext().VoidPtrTy); } enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; @@ -5522,8 +5518,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), FlagsLVal); } else - CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), - FlagsLVal.getType()); + CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType()); } if (Data.IsReductionWithTaskMod) { // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int @@ -5850,7 +5845,7 @@ void CGOpenMPRuntime::emitUsesAllocatorsInit(CodeGenFunction &CGF, .getLimitedValue()); LValue AllocatorTraitsLVal = CGF.EmitLValue(AllocatorTraits); Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - AllocatorTraitsLVal.getAddress(CGF), CGF.VoidPtrPtrTy, CGF.VoidPtrTy); + AllocatorTraitsLVal.getAddress(), CGF.VoidPtrPtrTy, CGF.VoidPtrTy); AllocatorTraitsLVal = CGF.MakeAddrLValue(Addr, CGF.getContext().VoidPtrTy, AllocatorTraitsLVal.getBaseInfo(), AllocatorTraitsLVal.getTBAAInfo()); @@ -7043,7 +7038,7 @@ private: } else if ((AE && isa(AE->getBase()->IgnoreParenImpCasts())) || (OASE && isa(OASE->getBase()->IgnoreParenImpCasts()))) { - BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); + BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(); } else if (OAShE && isa(OAShE->getBase()->IgnoreParenCasts())) { BP = Address( @@ -7053,7 +7048,7 @@ private: } else { // The base is the reference to the variable. // BP = &Var. - BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); + BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(); if (const auto *VD = dyn_cast_or_null(I->getAssociatedDeclaration())) { if (std::optional Res = @@ -7252,13 +7247,13 @@ private: LValue BaseLVal = EmitMemberExprBase(CGF, ME); LowestElem = CGF.EmitLValueForFieldInitialization( BaseLVal, cast(MapDecl)) - .getAddress(CGF); + .getAddress(); LB = CGF.EmitLoadOfReferenceLValue(LowestElem, MapDecl->getType()) - .getAddress(CGF); + .getAddress(); } else { LowestElem = LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) - .getAddress(CGF); + .getAddress(); } // If this component is a pointer inside the base struct then we don't @@ -7316,11 +7311,11 @@ private: LValue BaseLVal = EmitMemberExprBase(CGF, ME); ComponentLB = CGF.EmitLValueForFieldInitialization(BaseLVal, FD) - .getAddress(CGF); + .getAddress(); } else { ComponentLB = CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) - .getAddress(CGF); + .getAddress(); } llvm::Value *ComponentLBPtr = ComponentLB.emitRawPointer(CGF); llvm::Value *LBPtr = LB.emitRawPointer(CGF); @@ -7449,7 +7444,7 @@ private: if (IsFinalArraySection) { Address HB = CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/false) - .getAddress(CGF); + .getAddress(); PartialStruct.HighestElem = {FieldIndex, HB}; } else { PartialStruct.HighestElem = {FieldIndex, LowestElem}; @@ -7462,7 +7457,7 @@ private: if (IsFinalArraySection) { Address HB = CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/false) - .getAddress(CGF); + .getAddress(); PartialStruct.HighestElem = {FieldIndex, HB}; } else { PartialStruct.HighestElem = {FieldIndex, LowestElem}; @@ -11634,7 +11629,7 @@ Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF, CGF.EmitStoreOfScalar( llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)), FiredLVal); - return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF); + return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(); } namespace { @@ -11820,7 +11815,7 @@ void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const FieldDecl* FiredDecl = std::get<2>(It->getSecond()); LValue PrivLVal = CGF.EmitLValue(FoundE); Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - PrivLVal.getAddress(CGF), + PrivLVal.getAddress(), CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy)), CGF.ConvertTypeForMem(StructTy)); LValue BaseLVal = diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp index 87496c8e488c..28da8662f5f6 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp @@ -1103,13 +1103,13 @@ void CGOpenMPRuntimeGPU::emitGenericVarsProlog(CodeGenFunction &CGF, VoidPtr, VarPtrTy, VD->getName() + "_on_stack"); LValue VarAddr = CGF.MakeNaturalAlignPointeeRawAddrLValue(CastedVoidPtr, VarTy); - Rec.second.PrivateAddr = VarAddr.getAddress(CGF); + Rec.second.PrivateAddr = VarAddr.getAddress(); Rec.second.GlobalizedVal = VoidPtr; // Assign the local allocation to the newly globalized location. if (EscapedParam) { CGF.EmitStoreOfScalar(ParValue, VarAddr); - I->getSecond().MappedParams->setVarAddr(CGF, VD, VarAddr.getAddress(CGF)); + I->getSecond().MappedParams->setVarAddr(CGF, VD, VarAddr.getAddress()); } if (auto *DI = CGF.getDebugInfo()) VoidPtr->setDebugLoc(DI->SourceLocToDebugLoc(VD->getLocation())); @@ -1123,7 +1123,7 @@ void CGOpenMPRuntimeGPU::emitGenericVarsProlog(CodeGenFunction &CGF, LValue Base = CGF.MakeAddrLValue(AddrSizePair.first, VD->getType(), CGM.getContext().getDeclAlign(VD), AlignmentSource::Decl); - I->getSecond().MappedParams->setVarAddr(CGF, VD, Base.getAddress(CGF)); + I->getSecond().MappedParams->setVarAddr(CGF, VD, Base.getAddress()); } I->getSecond().MappedParams->apply(CGF); } @@ -2226,7 +2226,7 @@ static llvm::Value *emitListToGlobalCopyFunction( Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); - Address GlobAddr = GlobLVal.getAddress(CGF); + Address GlobAddr = GlobLVal.getAddress(); GlobLVal.setAddress(Address(GlobAddr.emitRawPointer(CGF), CGF.ConvertTypeForMem(Private->getType()), GlobAddr.getAlignment())); @@ -2327,7 +2327,7 @@ static llvm::Value *emitListToGlobalReduceFunction( Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); - Address GlobAddr = GlobLVal.getAddress(CGF); + Address GlobAddr = GlobLVal.getAddress(); CGF.EmitStoreOfScalar(GlobAddr.emitRawPointer(CGF), Elem, /*Volatile=*/false, C.VoidPtrTy); if ((*IPriv)->getType()->isVariablyModifiedType()) { @@ -2433,7 +2433,7 @@ static llvm::Value *emitGlobalToListCopyFunction( Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); - Address GlobAddr = GlobLVal.getAddress(CGF); + Address GlobAddr = GlobLVal.getAddress(); GlobLVal.setAddress(Address(GlobAddr.emitRawPointer(CGF), CGF.ConvertTypeForMem(Private->getType()), GlobAddr.getAlignment())); @@ -2534,7 +2534,7 @@ static llvm::Value *emitGlobalToListReduceFunction( Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); - Address GlobAddr = GlobLVal.getAddress(CGF); + Address GlobAddr = GlobLVal.getAddress(); CGF.EmitStoreOfScalar(GlobAddr.emitRawPointer(CGF), Elem, /*Volatile=*/false, C.VoidPtrTy); if ((*IPriv)->getType()->isVariablyModifiedType()) { @@ -3406,7 +3406,7 @@ void CGOpenMPRuntimeGPU::adjustTargetSpecificDataForLambdas( if (VD->getType().getCanonicalType()->isReferenceType()) VDAddr = CGF.EmitLoadOfReferenceLValue(VDAddr, VD->getType().getCanonicalType()) - .getAddress(CGF); + .getAddress(); CGF.EmitStoreOfScalar(VDAddr.emitRawPointer(CGF), VarLVal); } } diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 36776846cd44..99daaa14cf3f 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -2372,13 +2372,12 @@ std::pair CodeGenFunction::EmitAsmInputLValue( getTargetHooks().isScalarizableAsmOperand(*this, Ty)) { Ty = llvm::IntegerType::get(getLLVMContext(), Size); - return { - Builder.CreateLoad(InputValue.getAddress(*this).withElementType(Ty)), - nullptr}; + return {Builder.CreateLoad(InputValue.getAddress().withElementType(Ty)), + nullptr}; } } - Address Addr = InputValue.getAddress(*this); + Address Addr = InputValue.getAddress(); ConstraintStr += '*'; return {InputValue.getPointer(*this), Addr.getElementType()}; } @@ -2574,7 +2573,7 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S, // ResultTypeRequiresCast.size() elements of RegResults. if ((i < ResultTypeRequiresCast.size()) && ResultTypeRequiresCast[i]) { unsigned Size = CGF.getContext().getTypeSize(ResultRegQualTys[i]); - Address A = Dest.getAddress(CGF).withElementType(ResultRegTypes[i]); + Address A = Dest.getAddress().withElementType(ResultRegTypes[i]); if (CGF.getTargetHooks().isScalarizableAsmOperand(CGF, TruncTy)) { Builder.CreateStore(Tmp, A); continue; @@ -2776,7 +2775,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { std::max((uint64_t)LargestVectorWidth, VT->getPrimitiveSizeInBits().getKnownMinValue()); } else { - Address DestAddr = Dest.getAddress(*this); + Address DestAddr = Dest.getAddress(); // Matrix types in memory are represented by arrays, but accessed through // vector pointers, with the alignment specified on the access operation. // For inline assembly, update pointer arguments to use vector pointers. @@ -3124,7 +3123,7 @@ CodeGenFunction::EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K) { Address CodeGenFunction::GenerateCapturedStmtArgument(const CapturedStmt &S) { LValue CapStruct = InitCapturedStruct(S); - return CapStruct.getAddress(*this); + return CapStruct.getAddress(); } /// Creates the outlined function for a CapturedStmt. diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index ef3aa3a8e0dc..eac5ef326293 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -100,7 +100,7 @@ public: isCapturedVar(CGF, VD) || (CGF.CapturedStmtInfo && InlinedShareds.isGlobalVarCaptured(VD)), VD->getType().getNonReferenceType(), VK_LValue, C.getLocation()); - InlinedShareds.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress(CGF)); + InlinedShareds.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress()); } } (void)InlinedShareds.Privatize(); @@ -276,7 +276,7 @@ public: InlinedShareds.isGlobalVarCaptured(VD)), VD->getType().getNonReferenceType(), VK_LValue, C.getLocation()); - InlinedShareds.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress(CGF)); + InlinedShareds.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress()); } } CS = dyn_cast(CS->getCapturedStmt()); @@ -369,8 +369,7 @@ void CodeGenFunction::GenerateOpenMPCapturedVars( CapturedVars.push_back(CV); } else { assert(CurCap->capturesVariable() && "Expected capture by reference."); - CapturedVars.push_back( - EmitLValue(*I).getAddress(*this).emitRawPointer(*this)); + CapturedVars.push_back(EmitLValue(*I).getAddress().emitRawPointer(*this)); } } } @@ -381,11 +380,11 @@ static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, ASTContext &Ctx = CGF.getContext(); llvm::Value *CastedPtr = CGF.EmitScalarConversion( - AddrLV.getAddress(CGF).emitRawPointer(CGF), Ctx.getUIntPtrType(), + AddrLV.getAddress().emitRawPointer(CGF), Ctx.getUIntPtrType(), Ctx.getPointerType(DstType), Loc); // FIXME: should the pointee type (DstType) be passed? Address TmpAddr = - CGF.MakeNaturalAlignAddrLValue(CastedPtr, DstType).getAddress(CGF); + CGF.MakeNaturalAlignAddrLValue(CastedPtr, DstType).getAddress(); return TmpAddr; } @@ -578,7 +577,7 @@ static llvm::Function *emitOutlinedFunctionPrologue( } else if (I->capturesVariable()) { const VarDecl *Var = I->getCapturedVar(); QualType VarTy = Var->getType(); - Address ArgAddr = ArgLVal.getAddress(CGF); + Address ArgAddr = ArgLVal.getAddress(); if (ArgLVal.getType()->isLValueReferenceType()) { ArgAddr = CGF.EmitLoadOfReference(ArgLVal); } else if (!VarTy->isVariablyModifiedType() || !VarTy->isPointerType()) { @@ -599,12 +598,12 @@ static llvm::Function *emitOutlinedFunctionPrologue( ? castValueFromUintptr( CGF, I->getLocation(), FD->getType(), Args[Cnt]->getName(), ArgLVal) - : ArgLVal.getAddress(CGF)}}); + : ArgLVal.getAddress()}}); } else { // If 'this' is captured, load it into CXXThisValue. assert(I->capturesThis()); CXXThisValue = CGF.EmitLoadOfScalar(ArgLVal, I->getLocation()); - LocalAddrs.insert({Args[Cnt], {nullptr, ArgLVal.getAddress(CGF)}}); + LocalAddrs.insert({Args[Cnt], {nullptr, ArgLVal.getAddress()}}); } ++Cnt; ++I; @@ -674,7 +673,7 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, I->second.first ? I->second.first->getType() : Arg->getType(), AlignmentSource::Decl); if (LV.getType()->isAnyComplexType()) - LV.setAddress(LV.getAddress(WrapperCGF).withElementType(PI->getType())); + LV.setAddress(LV.getAddress().withElementType(PI->getType())); CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getBeginLoc()); } else { auto EI = VLASizes.find(Arg); @@ -890,8 +889,7 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D, EmitAggregateAssign(Dest, OriginalLVal, Type); } else { EmitOMPAggregateAssign( - Emission.getAllocatedAddress(), OriginalLVal.getAddress(*this), - Type, + Emission.getAllocatedAddress(), OriginalLVal.getAddress(), Type, [this, VDInit, Init](Address DestElement, Address SrcElement) { // Clean up any temporaries needed by the // initialization. @@ -908,7 +906,7 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D, IsRegistered = PrivateScope.addPrivate(OrigVD, Emission.getAllocatedAddress()); } else { - Address OriginalAddr = OriginalLVal.getAddress(*this); + Address OriginalAddr = OriginalLVal.getAddress(); // Emit private VarDecl with copy init. // Remap temp VDInit variable to the address of the original // variable (for proper handling of captured global variables). @@ -997,7 +995,7 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) { "Copyin threadprivates should have been captured!"); DeclRefExpr DRE(getContext(), const_cast(VD), true, (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc()); - MasterAddr = EmitLValue(&DRE).getAddress(*this); + MasterAddr = EmitLValue(&DRE).getAddress(); LocalDeclMap.erase(VD); } else { MasterAddr = @@ -1007,7 +1005,7 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) { getContext().getDeclAlign(VD)); } // Get the address of the threadprivate variable. - Address PrivateAddr = EmitLValue(*IRef).getAddress(*this); + Address PrivateAddr = EmitLValue(*IRef).getAddress(); if (CopiedVars.size() == 1) { // At first check if current thread is a master thread. If it is, no // need to copy data. @@ -1076,7 +1074,7 @@ bool CodeGenFunction::EmitOMPLastprivateClauseInit( /*RefersToEnclosingVariableOrCapture=*/ CapturedStmtInfo->lookup(OrigVD) != nullptr, (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc()); - PrivateScope.addPrivate(DestVD, EmitLValue(&DRE).getAddress(*this)); + PrivateScope.addPrivate(DestVD, EmitLValue(&DRE).getAddress()); // Check if the variable is also a firstprivate: in this case IInit is // not generated. Initialization of this variable will happen in codegen // for 'firstprivate' clause. @@ -1239,7 +1237,7 @@ void CodeGenFunction::EmitOMPReductionClauseInit( RedCG.emitAggregateType(*this, Count); AutoVarEmission Emission = EmitAutoVarAlloca(*PrivateVD); RedCG.emitInitialization(*this, Count, Emission.getAllocatedAddress(), - RedCG.getSharedLValue(Count).getAddress(*this), + RedCG.getSharedLValue(Count).getAddress(), [&Emission](CodeGenFunction &CGF) { CGF.EmitAutoVarInit(Emission); return true; @@ -1260,22 +1258,20 @@ void CodeGenFunction::EmitOMPReductionClauseInit( if (isaOMPArraySectionExpr && Type->isVariablyModifiedType()) { // Store the address of the original variable associated with the LHS // implicit variable. - PrivateScope.addPrivate(LHSVD, - RedCG.getSharedLValue(Count).getAddress(*this)); + PrivateScope.addPrivate(LHSVD, RedCG.getSharedLValue(Count).getAddress()); PrivateScope.addPrivate(RHSVD, GetAddrOfLocalVar(PrivateVD)); } else if ((isaOMPArraySectionExpr && Type->isScalarType()) || isa(IRef)) { // Store the address of the original variable associated with the LHS // implicit variable. - PrivateScope.addPrivate(LHSVD, - RedCG.getSharedLValue(Count).getAddress(*this)); + PrivateScope.addPrivate(LHSVD, RedCG.getSharedLValue(Count).getAddress()); PrivateScope.addPrivate(RHSVD, GetAddrOfLocalVar(PrivateVD).withElementType( ConvertTypeForMem(RHSVD->getType()))); } else { QualType Type = PrivateVD->getType(); bool IsArray = getContext().getAsArrayType(Type) != nullptr; - Address OriginalAddr = RedCG.getSharedLValue(Count).getAddress(*this); + Address OriginalAddr = RedCG.getSharedLValue(Count).getAddress(); // Store the address of the original variable associated with the LHS // implicit variable. if (IsArray) { @@ -2069,7 +2065,7 @@ void CodeGenFunction::EmitOMPCanonicalLoop(const OMPCanonicalLoop *S) { // variable and emit the body. const DeclRefExpr *LoopVarRef = S->getLoopVarRef(); LValue LCVal = EmitLValue(LoopVarRef); - Address LoopVarAddress = LCVal.getAddress(*this); + Address LoopVarAddress = LCVal.getAddress(); emitCapturedStmtCall(*this, LoopVarClosure, {LoopVarAddress.emitRawPointer(*this), IndVar}); @@ -2210,7 +2206,7 @@ void CodeGenFunction::EmitOMPLinearClauseFinal( DeclRefExpr DRE(getContext(), const_cast(OrigVD), CapturedStmtInfo->lookup(OrigVD) != nullptr, (*IC)->getType(), VK_LValue, (*IC)->getExprLoc()); - Address OrigAddr = EmitLValue(&DRE).getAddress(*this); + Address OrigAddr = EmitLValue(&DRE).getAddress(); CodeGenFunction::OMPPrivateScope VarScope(*this); VarScope.addPrivate(OrigVD, OrigAddr); (void)VarScope.Privatize(); @@ -2277,7 +2273,7 @@ void CodeGenFunction::EmitOMPPrivateLoopCounters( DeclRefExpr DRE(getContext(), const_cast(VD), LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD), E->getType(), VK_LValue, E->getExprLoc()); - (void)LoopScope.addPrivate(PrivateVD, EmitLValue(&DRE).getAddress(*this)); + (void)LoopScope.addPrivate(PrivateVD, EmitLValue(&DRE).getAddress()); } else { (void)LoopScope.addPrivate(PrivateVD, VarEmission.getAllocatedAddress()); } @@ -2443,13 +2439,12 @@ void CodeGenFunction::EmitOMPSimdFinal( } Address OrigAddr = Address::invalid(); if (CED) { - OrigAddr = - EmitLValue(CED->getInit()->IgnoreImpCasts()).getAddress(*this); + OrigAddr = EmitLValue(CED->getInit()->IgnoreImpCasts()).getAddress(); } else { DeclRefExpr DRE(getContext(), const_cast(PrivateVD), /*RefersToEnclosingVariableOrCapture=*/false, (*IPC)->getType(), VK_LValue, (*IPC)->getExprLoc()); - OrigAddr = EmitLValue(&DRE).getAddress(*this); + OrigAddr = EmitLValue(&DRE).getAddress(); } OMPPrivateScope VarScope(*this); VarScope.addPrivate(OrigVD, OrigAddr); @@ -3165,16 +3160,14 @@ static void emitDistributeParallelForDistributeInnerBoundParams( const auto &Dir = cast(S); LValue LB = CGF.EmitLValue(cast(Dir.getCombinedLowerBoundVariable())); - llvm::Value *LBCast = - CGF.Builder.CreateIntCast(CGF.Builder.CreateLoad(LB.getAddress(CGF)), - CGF.SizeTy, /*isSigned=*/false); + llvm::Value *LBCast = CGF.Builder.CreateIntCast( + CGF.Builder.CreateLoad(LB.getAddress()), CGF.SizeTy, /*isSigned=*/false); CapturedVars.push_back(LBCast); LValue UB = CGF.EmitLValue(cast(Dir.getCombinedUpperBoundVariable())); - llvm::Value *UBCast = - CGF.Builder.CreateIntCast(CGF.Builder.CreateLoad(UB.getAddress(CGF)), - CGF.SizeTy, /*isSigned=*/false); + llvm::Value *UBCast = CGF.Builder.CreateIntCast( + CGF.Builder.CreateLoad(UB.getAddress()), CGF.SizeTy, /*isSigned=*/false); CapturedVars.push_back(UBCast); } @@ -3426,8 +3419,8 @@ bool CodeGenFunction::EmitOMPWorksharingLoop( // one chunk is distributed to each thread. Note that the size of // the chunks is unspecified in this case. CGOpenMPRuntime::StaticRTInput StaticInit( - IVSize, IVSigned, Ordered, IL.getAddress(CGF), - LB.getAddress(CGF), UB.getAddress(CGF), ST.getAddress(CGF), + IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(), + UB.getAddress(), ST.getAddress(), StaticChunkedOne ? Chunk : nullptr); CGF.CGM.getOpenMPRuntime().emitForStaticInit( CGF, S.getBeginLoc(), S.getDirectiveKind(), ScheduleKind, @@ -3470,9 +3463,9 @@ bool CodeGenFunction::EmitOMPWorksharingLoop( } else { // Emit the outer loop, which requests its work chunk [LB..UB] from // runtime and runs the inner loop to process it. - OMPLoopArguments LoopArguments( - LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this), - IL.getAddress(*this), Chunk, EUB); + OMPLoopArguments LoopArguments(LB.getAddress(), UB.getAddress(), + ST.getAddress(), IL.getAddress(), Chunk, + EUB); LoopArguments.DKind = OMPD_for; EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered, LoopArguments, CGDispatchBounds); @@ -3639,11 +3632,10 @@ static void emitScanBasedDirectiveFinals( RValue::get(OMPLast)); LValue DestLVal = CGF.EmitLValue(OrigExpr); LValue SrcLVal = CGF.EmitLValue(CopyArrayElem); - CGF.EmitOMPCopy(PrivateExpr->getType(), DestLVal.getAddress(CGF), - SrcLVal.getAddress(CGF), - cast(cast(LHSs[I])->getDecl()), - cast(cast(RHSs[I])->getDecl()), - CopyOps[I]); + CGF.EmitOMPCopy( + PrivateExpr->getType(), DestLVal.getAddress(), SrcLVal.getAddress(), + cast(cast(LHSs[I])->getDecl()), + cast(cast(RHSs[I])->getDecl()), CopyOps[I]); } } @@ -3753,7 +3745,7 @@ static void emitScanBasedDirective( cast( cast(CopyArrayElem)->getIdx()), RValue::get(IVal)); - LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress(CGF); + LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress(); } PrivScope.addPrivate(LHSVD, LHSAddr); Address RHSAddr = Address::invalid(); @@ -3764,7 +3756,7 @@ static void emitScanBasedDirective( cast( cast(CopyArrayElem)->getIdx()), RValue::get(OffsetIVal)); - RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress(CGF); + RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress(); } PrivScope.addPrivate(RHSVD, RHSAddr); ++ILHS; @@ -4078,8 +4070,8 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) { OpenMPScheduleTy ScheduleKind; ScheduleKind.Schedule = OMPC_SCHEDULE_static; CGOpenMPRuntime::StaticRTInput StaticInit( - /*IVSize=*/32, /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(CGF), - LB.getAddress(CGF), UB.getAddress(CGF), ST.getAddress(CGF)); + /*IVSize=*/32, /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(), + LB.getAddress(), UB.getAddress(), ST.getAddress()); CGF.CGM.getOpenMPRuntime().emitForStaticInit( CGF, S.getBeginLoc(), S.getDirectiveKind(), ScheduleKind, StaticInit); // UB = min(UB, GlobalUB); @@ -4858,7 +4850,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( CGF.CapturedStmtInfo->lookup(OrigVD) != nullptr, Pair.second->getType(), VK_LValue, Pair.second->getExprLoc()); - Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress(CGF)); + Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress()); } for (const auto &Pair : PrivatePtrs) { Address Replacement = Address( @@ -5505,8 +5497,8 @@ void CodeGenFunction::EmitOMPScanDirective(const OMPScanDirective &S) { *cast(cast(TempExpr)->getDecl())); LValue DestLVal = EmitLValue(TempExpr); LValue SrcLVal = EmitLValue(LHSs[I]); - EmitOMPCopy(PrivateExpr->getType(), DestLVal.getAddress(*this), - SrcLVal.getAddress(*this), + EmitOMPCopy(PrivateExpr->getType(), DestLVal.getAddress(), + SrcLVal.getAddress(), cast(cast(LHSs[I])->getDecl()), cast(cast(RHSs[I])->getDecl()), CopyOps[I]); @@ -5527,11 +5519,10 @@ void CodeGenFunction::EmitOMPScanDirective(const OMPScanDirective &S) { DestLVal = EmitLValue(RHSs[I]); SrcLVal = EmitLValue(TempExpr); } - EmitOMPCopy(PrivateExpr->getType(), DestLVal.getAddress(*this), - SrcLVal.getAddress(*this), - cast(cast(LHSs[I])->getDecl()), - cast(cast(RHSs[I])->getDecl()), - CopyOps[I]); + EmitOMPCopy( + PrivateExpr->getType(), DestLVal.getAddress(), SrcLVal.getAddress(), + cast(cast(LHSs[I])->getDecl()), + cast(cast(RHSs[I])->getDecl()), CopyOps[I]); } } EmitBranch(IsInclusive ? OMPAfterScanBlock : OMPBeforeScanBlock); @@ -5564,11 +5555,10 @@ void CodeGenFunction::EmitOMPScanDirective(const OMPScanDirective &S) { RValue::get(IdxVal)); LValue DestLVal = EmitLValue(CopyArrayElem); LValue SrcLVal = EmitLValue(OrigExpr); - EmitOMPCopy(PrivateExpr->getType(), DestLVal.getAddress(*this), - SrcLVal.getAddress(*this), - cast(cast(LHSs[I])->getDecl()), - cast(cast(RHSs[I])->getDecl()), - CopyOps[I]); + EmitOMPCopy( + PrivateExpr->getType(), DestLVal.getAddress(), SrcLVal.getAddress(), + cast(cast(LHSs[I])->getDecl()), + cast(cast(RHSs[I])->getDecl()), CopyOps[I]); } } EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock()); @@ -5606,11 +5596,10 @@ void CodeGenFunction::EmitOMPScanDirective(const OMPScanDirective &S) { RValue::get(IdxVal)); LValue SrcLVal = EmitLValue(CopyArrayElem); LValue DestLVal = EmitLValue(OrigExpr); - EmitOMPCopy(PrivateExpr->getType(), DestLVal.getAddress(*this), - SrcLVal.getAddress(*this), - cast(cast(LHSs[I])->getDecl()), - cast(cast(RHSs[I])->getDecl()), - CopyOps[I]); + EmitOMPCopy( + PrivateExpr->getType(), DestLVal.getAddress(), SrcLVal.getAddress(), + cast(cast(LHSs[I])->getDecl()), + cast(cast(RHSs[I])->getDecl()), CopyOps[I]); } if (!IsInclusive) { EmitBlock(ExclusiveExitBB); @@ -5735,8 +5724,8 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S, /* Chunked */ Chunk != nullptr) || StaticChunked) { CGOpenMPRuntime::StaticRTInput StaticInit( - IVSize, IVSigned, /* Ordered = */ false, IL.getAddress(*this), - LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this), + IVSize, IVSigned, /* Ordered = */ false, IL.getAddress(), + LB.getAddress(), UB.getAddress(), ST.getAddress(), StaticChunked ? Chunk : nullptr); RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind, StaticInit); @@ -5812,8 +5801,8 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S, // Emit the outer loop, which requests its work chunk [LB..UB] from // runtime and runs the inner loop to process it. const OMPLoopArguments LoopArguments = { - LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this), - IL.getAddress(*this), Chunk}; + LB.getAddress(), UB.getAddress(), ST.getAddress(), IL.getAddress(), + Chunk}; EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments, CodeGenLoop); } @@ -6127,8 +6116,7 @@ static std::pair emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, // target platform. if (BO == BO_Comma || !Update.isScalar() || !X.isSimple() || (!isa(Update.getScalarVal()) && - (Update.getScalarVal()->getType() != - X.getAddress(CGF).getElementType())) || + (Update.getScalarVal()->getType() != X.getAddress().getElementType())) || !Context.getTargetInfo().hasBuiltinAtomic( Context.getTypeSize(X.getType()), Context.toBits(X.getAlignment()))) return std::make_pair(false, RValue::get(nullptr)); @@ -6144,10 +6132,10 @@ static std::pair emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, }; if (!CheckAtomicSupport(Update.getScalarVal()->getType(), BO) || - !CheckAtomicSupport(X.getAddress(CGF).getElementType(), BO)) + !CheckAtomicSupport(X.getAddress().getElementType(), BO)) return std::make_pair(false, RValue::get(nullptr)); - bool IsInteger = X.getAddress(CGF).getElementType()->isIntegerTy(); + bool IsInteger = X.getAddress().getElementType()->isIntegerTy(); llvm::AtomicRMWInst::BinOp RMWOp; switch (BO) { case BO_Add: @@ -6224,14 +6212,14 @@ static std::pair emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, if (auto *IC = dyn_cast(UpdateVal)) { if (IsInteger) UpdateVal = CGF.Builder.CreateIntCast( - IC, X.getAddress(CGF).getElementType(), + IC, X.getAddress().getElementType(), X.getType()->hasSignedIntegerRepresentation()); else UpdateVal = CGF.Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC, - X.getAddress(CGF).getElementType()); + X.getAddress().getElementType()); } llvm::Value *Res = - CGF.Builder.CreateAtomicRMW(RMWOp, X.getAddress(CGF), UpdateVal, AO); + CGF.Builder.CreateAtomicRMW(RMWOp, X.getAddress(), UpdateVal, AO); return std::make_pair(true, RValue::get(Res)); } @@ -6456,7 +6444,7 @@ static void emitOMPAtomicCompareExpr( } LValue XLVal = CGF.EmitLValue(X); - Address XAddr = XLVal.getAddress(CGF); + Address XAddr = XLVal.getAddress(); auto EmitRValueWithCastIfNeeded = [&CGF, Loc](const Expr *X, const Expr *E) { if (X->getType() == E->getType()) @@ -6472,12 +6460,12 @@ static void emitOMPAtomicCompareExpr( llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(X, D) : nullptr; if (auto *CI = dyn_cast(EVal)) EVal = CGF.Builder.CreateIntCast( - CI, XLVal.getAddress(CGF).getElementType(), + CI, XLVal.getAddress().getElementType(), E->getType()->hasSignedIntegerRepresentation()); if (DVal) if (auto *CI = dyn_cast(DVal)) DVal = CGF.Builder.CreateIntCast( - CI, XLVal.getAddress(CGF).getElementType(), + CI, XLVal.getAddress().getElementType(), D->getType()->hasSignedIntegerRepresentation()); llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{ @@ -6487,14 +6475,14 @@ static void emitOMPAtomicCompareExpr( llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal; if (V) { LValue LV = CGF.EmitLValue(V); - Address Addr = LV.getAddress(CGF); + Address Addr = LV.getAddress(); VOpVal = {Addr.emitRawPointer(CGF), Addr.getElementType(), V->getType()->hasSignedIntegerRepresentation(), V->getType().isVolatileQualified()}; } if (R) { LValue LV = CGF.EmitLValue(R); - Address Addr = LV.getAddress(CGF); + Address Addr = LV.getAddress(); ROpVal = {Addr.emitRawPointer(CGF), Addr.getElementType(), R->getType()->hasSignedIntegerRepresentation(), R->getType().isVolatileQualified()}; @@ -8127,7 +8115,7 @@ void CodeGenFunction::EmitSimpleOMPExecutableDirective( continue; if (!CGF.LocalDeclMap.count(VD)) { LValue GlobLVal = CGF.EmitLValue(Ref); - GlobalsScope.addPrivate(VD, GlobLVal.getAddress(CGF)); + GlobalsScope.addPrivate(VD, GlobLVal.getAddress()); } } } @@ -8142,7 +8130,7 @@ void CodeGenFunction::EmitSimpleOMPExecutableDirective( const auto *VD = cast(cast(E)->getDecl()); if (!VD->hasLocalStorage() && !CGF.LocalDeclMap.count(VD)) { LValue GlobLVal = CGF.EmitLValue(E); - GlobalsScope.addPrivate(VD, GlobLVal.getAddress(CGF)); + GlobalsScope.addPrivate(VD, GlobLVal.getAddress()); } if (isa(VD)) { // Emit only those that were not explicitly referenced in clauses. diff --git a/clang/lib/CodeGen/CGValue.h b/clang/lib/CodeGen/CGValue.h index cc9ad10ae596..f1ba3cf95ae5 100644 --- a/clang/lib/CodeGen/CGValue.h +++ b/clang/lib/CodeGen/CGValue.h @@ -367,10 +367,7 @@ public: return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; } - Address getAddress(CodeGenFunction &CGF) const { - // FIXME: remove parameter. - return Addr; - } + Address getAddress() const { return Addr; } void setAddress(Address address) { Addr = address; } @@ -503,8 +500,8 @@ public: return R; } - RValue asAggregateRValue(CodeGenFunction &CGF) const { - return RValue::getAggregate(getAddress(CGF), isVolatileQualified()); + RValue asAggregateRValue() const { + return RValue::getAggregate(getAddress(), isVolatileQualified()); } }; @@ -607,11 +604,11 @@ public: } static AggValueSlot - forLValue(const LValue &LV, CodeGenFunction &CGF, IsDestructed_t isDestructed, + forLValue(const LValue &LV, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed = IsNotZeroed, IsSanitizerChecked_t isChecked = IsNotSanitizerChecked) { - return forAddr(LV.getAddress(CGF), LV.getQuals(), isDestructed, needsGC, + return forAddr(LV.getAddress(), LV.getQuals(), isDestructed, needsGC, isAliased, mayOverlap, isZeroed, isChecked); } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 04abdadd9537..f0345f3b191b 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -2478,11 +2478,11 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { Address CodeGenFunction::EmitVAListRef(const Expr* E) { if (getContext().getBuiltinVaListType()->isArrayType()) return EmitPointerWithAlignment(E); - return EmitLValue(E).getAddress(*this); + return EmitLValue(E).getAddress(); } Address CodeGenFunction::EmitMSVAListRef(const Expr *E) { - return EmitLValue(E).getAddress(*this); + return EmitLValue(E).getAddress(); } void CodeGenFunction::EmitDeclRefExprDbgValue(const DeclRefExpr *E, diff --git a/clang/lib/CodeGen/Targets/NVPTX.cpp b/clang/lib/CodeGen/Targets/NVPTX.cpp index 7dce5042c3dc..df798ce0ca67 100644 --- a/clang/lib/CodeGen/Targets/NVPTX.cpp +++ b/clang/lib/CodeGen/Targets/NVPTX.cpp @@ -85,7 +85,7 @@ private: LValue Src) { llvm::Value *Handle = nullptr; llvm::Constant *C = - llvm::dyn_cast(Src.getAddress(CGF).emitRawPointer(CGF)); + llvm::dyn_cast(Src.getAddress().emitRawPointer(CGF)); // Lookup `addrspacecast` through the constant pointer if any. if (auto *ASC = llvm::dyn_cast_or_null(C)) C = llvm::cast(ASC->getPointerOperand()); diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 29d98aad8fcb..43dadf5e724a 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -327,7 +327,7 @@ void X86_32TargetCodeGenInfo::addReturnRegisterOutputs( ResultTruncRegTypes.push_back(CoerceTy); // Coerce the integer by bitcasting the return slot pointer. - ReturnSlot.setAddress(ReturnSlot.getAddress(CGF).withElementType(CoerceTy)); + ReturnSlot.setAddress(ReturnSlot.getAddress().withElementType(CoerceTy)); ResultRegDests.push_back(ReturnSlot); rewriteInputConstraintReferences(NumOutputs, 1, AsmString); -- GitLab From 285f1392da07f6b0bcaa7d106c00b1e9fda25333 Mon Sep 17 00:00:00 2001 From: David Green Date: Mon, 20 May 2024 18:27:33 +0100 Subject: [PATCH 108/793] [VectorCombine] Some more tests for different cmp's and fp consts. NFC --- .../AArch64/shuffletoidentity.ll | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll b/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll index bb333941abf7..eb368471b1d8 100644 --- a/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll +++ b/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll @@ -317,6 +317,23 @@ define <8 x i8> @constantdiff2(<8 x i8> %a) { ret <8 x i8> %r } +define <8 x half> @constantsplatf(<8 x half> %a) { +; CHECK-LABEL: @constantsplatf( +; CHECK-NEXT: [[AB:%.*]] = shufflevector <8 x half> [[A:%.*]], <8 x half> poison, <4 x i32> +; CHECK-NEXT: [[AT:%.*]] = shufflevector <8 x half> [[A]], <8 x half> poison, <4 x i32> +; CHECK-NEXT: [[ABT:%.*]] = fadd <4 x half> [[AT]], +; CHECK-NEXT: [[ABB:%.*]] = fadd <4 x half> [[AB]], +; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x half> [[ABT]], <4 x half> [[ABB]], <8 x i32> +; CHECK-NEXT: ret <8 x half> [[R]] +; + %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> + %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> + %abt = fadd <4 x half> %at, + %abb = fadd <4 x half> %ab, + %r = shufflevector <4 x half> %abt, <4 x half> %abb, <8 x i32> + ret <8 x half> %r +} + define <8 x i8> @inner_shuffle(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) { ; CHECK-LABEL: @inner_shuffle( ; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <8 x i8> [[C:%.*]], <8 x i8> poison, <8 x i32> zeroinitializer @@ -413,6 +430,72 @@ define <8 x i8> @icmpsel(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c, <8 x i8> %d) { ret <8 x i8> %r } +define <8 x i8> @icmpsel_diffentcond(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c, <8 x i8> %d) { +; CHECK-LABEL: @icmpsel_diffentcond( +; CHECK-NEXT: [[AB:%.*]] = shufflevector <8 x i8> [[A:%.*]], <8 x i8> poison, <4 x i32> +; CHECK-NEXT: [[AT:%.*]] = shufflevector <8 x i8> [[A]], <8 x i8> poison, <4 x i32> +; CHECK-NEXT: [[BB:%.*]] = shufflevector <8 x i8> [[B:%.*]], <8 x i8> poison, <4 x i32> +; CHECK-NEXT: [[BT:%.*]] = shufflevector <8 x i8> [[B]], <8 x i8> poison, <4 x i32> +; CHECK-NEXT: [[CB:%.*]] = shufflevector <8 x i8> [[C:%.*]], <8 x i8> poison, <4 x i32> +; CHECK-NEXT: [[CT:%.*]] = shufflevector <8 x i8> [[C]], <8 x i8> poison, <4 x i32> +; CHECK-NEXT: [[DB:%.*]] = shufflevector <8 x i8> [[D:%.*]], <8 x i8> poison, <4 x i32> +; CHECK-NEXT: [[DT:%.*]] = shufflevector <8 x i8> [[D]], <8 x i8> poison, <4 x i32> +; CHECK-NEXT: [[ABT1:%.*]] = icmp slt <4 x i8> [[AT]], [[BT]] +; CHECK-NEXT: [[ABB1:%.*]] = icmp ult <4 x i8> [[AB]], [[BB]] +; CHECK-NEXT: [[ABT:%.*]] = select <4 x i1> [[ABT1]], <4 x i8> [[CT]], <4 x i8> [[DT]] +; CHECK-NEXT: [[ABB:%.*]] = select <4 x i1> [[ABB1]], <4 x i8> [[CB]], <4 x i8> [[DB]] +; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[ABT]], <4 x i8> [[ABB]], <8 x i32> +; CHECK-NEXT: ret <8 x i8> [[R]] +; + %ab = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> + %at = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> + %bb = shufflevector <8 x i8> %b, <8 x i8> poison, <4 x i32> + %bt = shufflevector <8 x i8> %b, <8 x i8> poison, <4 x i32> + %cb = shufflevector <8 x i8> %c, <8 x i8> poison, <4 x i32> + %ct = shufflevector <8 x i8> %c, <8 x i8> poison, <4 x i32> + %db = shufflevector <8 x i8> %d, <8 x i8> poison, <4 x i32> + %dt = shufflevector <8 x i8> %d, <8 x i8> poison, <4 x i32> + %abt1 = icmp slt <4 x i8> %at, %bt + %abb1 = icmp ult <4 x i8> %ab, %bb + %abt = select <4 x i1> %abt1, <4 x i8> %ct, <4 x i8> %dt + %abb = select <4 x i1> %abb1, <4 x i8> %cb, <4 x i8> %db + %r = shufflevector <4 x i8> %abt, <4 x i8> %abb, <8 x i32> + ret <8 x i8> %r +} + +define <8 x i8> @fcmpsel(<8 x half> %a, <8 x half> %b, <8 x i8> %c, <8 x i8> %d) { +; CHECK-LABEL: @fcmpsel( +; CHECK-NEXT: [[AB:%.*]] = shufflevector <8 x half> [[A:%.*]], <8 x half> poison, <4 x i32> +; CHECK-NEXT: [[AT:%.*]] = shufflevector <8 x half> [[A]], <8 x half> poison, <4 x i32> +; CHECK-NEXT: [[BB:%.*]] = shufflevector <8 x half> [[B:%.*]], <8 x half> poison, <4 x i32> +; CHECK-NEXT: [[BT:%.*]] = shufflevector <8 x half> [[B]], <8 x half> poison, <4 x i32> +; CHECK-NEXT: [[CB:%.*]] = shufflevector <8 x i8> [[C:%.*]], <8 x i8> poison, <4 x i32> +; CHECK-NEXT: [[CT:%.*]] = shufflevector <8 x i8> [[C]], <8 x i8> poison, <4 x i32> +; CHECK-NEXT: [[DB:%.*]] = shufflevector <8 x i8> [[D:%.*]], <8 x i8> poison, <4 x i32> +; CHECK-NEXT: [[DT:%.*]] = shufflevector <8 x i8> [[D]], <8 x i8> poison, <4 x i32> +; CHECK-NEXT: [[ABT1:%.*]] = fcmp olt <4 x half> [[AT]], [[BT]] +; CHECK-NEXT: [[ABB1:%.*]] = fcmp olt <4 x half> [[AB]], [[BB]] +; CHECK-NEXT: [[ABT:%.*]] = select <4 x i1> [[ABT1]], <4 x i8> [[CT]], <4 x i8> [[DT]] +; CHECK-NEXT: [[ABB:%.*]] = select <4 x i1> [[ABB1]], <4 x i8> [[CB]], <4 x i8> [[DB]] +; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[ABT]], <4 x i8> [[ABB]], <8 x i32> +; CHECK-NEXT: ret <8 x i8> [[R]] +; + %ab = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> + %at = shufflevector <8 x half> %a, <8 x half> poison, <4 x i32> + %bb = shufflevector <8 x half> %b, <8 x half> poison, <4 x i32> + %bt = shufflevector <8 x half> %b, <8 x half> poison, <4 x i32> + %cb = shufflevector <8 x i8> %c, <8 x i8> poison, <4 x i32> + %ct = shufflevector <8 x i8> %c, <8 x i8> poison, <4 x i32> + %db = shufflevector <8 x i8> %d, <8 x i8> poison, <4 x i32> + %dt = shufflevector <8 x i8> %d, <8 x i8> poison, <4 x i32> + %abt1 = fcmp olt <4 x half> %at, %bt + %abb1 = fcmp olt <4 x half> %ab, %bb + %abt = select <4 x i1> %abt1, <4 x i8> %ct, <4 x i8> %dt + %abb = select <4 x i1> %abb1, <4 x i8> %cb, <4 x i8> %db + %r = shufflevector <4 x i8> %abt, <4 x i8> %abb, <8 x i32> + ret <8 x i8> %r +} + define <8 x half> @fma(<8 x half> %a, <8 x half> %b, <8 x half> %c) { ; CHECK-LABEL: @fma( ; CHECK-NEXT: [[R:%.*]] = call <8 x half> @llvm.fma.v8f16(<8 x half> [[A:%.*]], <8 x half> [[B:%.*]], <8 x half> [[C:%.*]]) -- GitLab From a0e3e76385feca289f03576b17d5e9cc7783c9b4 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Fri, 17 May 2024 10:18:38 -0700 Subject: [PATCH 109/793] [mlir] Remove redundant include in Passes.h header (NFC) --- mlir/include/mlir/Dialect/Math/Transforms/Passes.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mlir/include/mlir/Dialect/Math/Transforms/Passes.h b/mlir/include/mlir/Dialect/Math/Transforms/Passes.h index ba6977251564..2dd7f6431f03 100644 --- a/mlir/include/mlir/Dialect/Math/Transforms/Passes.h +++ b/mlir/include/mlir/Dialect/Math/Transforms/Passes.h @@ -14,10 +14,6 @@ namespace mlir { namespace math { #define GEN_PASS_DECL -#include "mlir/Dialect/Math/Transforms/Passes.h.inc" -#define GEN_PASS_DECL_MATHUPLIFTTOFMA -#define GEN_PASS_DECL_MATHLEGALIZETOF32 -#include "mlir/Dialect/Math/Transforms/Passes.h.inc" #define GEN_PASS_REGISTRATION #include "mlir/Dialect/Math/Transforms/Passes.h.inc" } // namespace math -- GitLab From e24610532b87eaae06dedec8f7c90764cd9ba19c Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Mon, 20 May 2024 17:32:47 +0000 Subject: [PATCH 110/793] [gn build] Port 4f5bc4bb55a8 --- llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn index f6c9526278dd..188c71805f27 100644 --- a/llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn @@ -84,7 +84,7 @@ static_library("Sema") { "SemaOpenMP.cpp", "SemaOverload.cpp", "SemaPseudoObject.cpp", - "SemaRISCVVectorLookup.cpp", + "SemaRISCV.cpp", "SemaSYCL.cpp", "SemaStmt.cpp", "SemaStmtAsm.cpp", -- GitLab From fd87d765c0455265aea4595a3741a96b4c078fbc Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 20 May 2024 13:55:01 -0400 Subject: [PATCH 111/793] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions (#92318) According to [expr.prim.id.general] p2: > If an _id-expression_ `E` denotes a non-static non-type member of some class `C` at a point where the current class is `X` and > - `E` is potentially evaluated or `C` is `X` or a base class of `X`, and > - `E` is not the _id-expression_ of a class member access expression, and > - if `E` is a _qualified-id_, `E` is not the un-parenthesized operand of the unary `&` operator, > > the _id-expression_ is transformed into a class member access expression using `(*this)` as the object expression. Consider the following: ``` struct A { void f0(); template void f1(); }; template struct B : T { auto g0() -> decltype(T::f0()); // ok auto g1() -> decltype(T::template f1()); // error: call to non-static member function without an object argument }; template struct B; ``` Clang incorrectly rejects the call to `f1` in the _trailing-return-type_ of `g1`. Furthermore, the following snippet results in a crash during codegen: ``` struct A { void f(); }; template struct B : T { template static void g(); template<> void g() { return T::f(); // crash here } }; template struct B; ``` This happens because we unconditionally build a `CXXDependentScopeMemberExpr` (with an implicit object expression) for `T::f` when parsing the template definition, even though we don't know whether `g` is an implicit object member function yet. This patch fixes these issues by instead building `DependentScopeDeclRefExpr`s for such expressions, and only transforming them into implicit class member access expressions during instantiation. Since we implemented the MS "unqualified lookup into dependent bases" extension by building an implicit class member access (and relying on the first component name of the _nested-name-specifier_ to be looked up in the context of the object expression during instantiation), we instead pre-append a fake _nested-name-specifier_ that refers to the injected-class-name of the enclosing class. This patch also refactors `Sema::BuildQualifiedDeclarationNameExpr` and `Sema::BuildQualifiedTemplateIdExpr`, streamlining their implementation and removing any redundant checks. --- clang/docs/ReleaseNotes.rst | 2 + clang/include/clang/Sema/Sema.h | 11 +- clang/lib/Sema/SemaCXXScopeSpec.cpp | 8 ++ clang/lib/Sema/SemaExpr.cpp | 65 ++--------- clang/lib/Sema/SemaLookup.cpp | 9 +- clang/lib/Sema/SemaTemplate.cpp | 105 ++++++------------ clang/lib/Sema/TreeTransform.h | 6 +- .../class.mfct/class.mfct.non-static/p3.cpp | 91 ++++++++++++++- ...ms-function-specialization-class-scope.cpp | 52 +++++++++ .../ms-lookup-template-base-classes.cpp | 12 +- .../ASTMatchers/ASTMatchersNodeTest.cpp | 6 +- 11 files changed, 222 insertions(+), 145 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a89e10524aa1..ba4637d98197 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -744,6 +744,8 @@ Bug Fixes to C++ Support explicit object argument member functions. Fixes (#GH92188). - Fix a C++11 crash when a non-const non-static member function is defined out-of-line with the ``constexpr`` specifier. Fixes (#GH61004). +- Clang no longer transforms dependent qualified names into implicit class member access expressions + until it can be determined whether the name is that of a non-static member. Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6c89d275215d..5894239664c1 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5375,11 +5375,9 @@ public: bool UseArgumentDependentLookup(const CXXScopeSpec &SS, const LookupResult &R, bool HasTrailingLParen); - ExprResult - BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, - const DeclarationNameInfo &NameInfo, - bool IsAddressOfOperand, const Scope *S, - TypeSourceInfo **RecoveryTSI = nullptr); + ExprResult BuildQualifiedDeclarationNameExpr( + CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, + bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI = nullptr); ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, @@ -8991,7 +8989,8 @@ public: ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs, + bool IsAddressOfOperand); TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index fca5bd131bbc..c405fbc0aa42 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -796,6 +796,14 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, Diag(IdInfo.IdentifierLoc, diag::ext_undeclared_unqual_id_with_dependent_base) << IdInfo.Identifier << ContainingClass; + // Fake up a nested-name-specifier that starts with the + // injected-class-name of the enclosing class. + QualType T = Context.getTypeDeclType(ContainingClass); + TypeLocBuilder TLB; + TLB.pushTrivial(Context, T, IdInfo.IdentifierLoc); + SS.Extend(Context, /*TemplateKWLoc=*/SourceLocation(), + TLB.getTypeLocInContext(Context, T), IdInfo.IdentifierLoc); + // Add the identifier to form a dependent name. SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc, IdInfo.CCLoc); return false; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index f2d0a93d9a1e..e7731e389c1b 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2718,34 +2718,6 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, return ExprError(); } - // C++ [temp.dep.expr]p3: - // An id-expression is type-dependent if it contains: - // -- an identifier that was declared with a dependent type, - // (note: handled after lookup) - // -- a template-id that is dependent, - // (note: handled in BuildTemplateIdExpr) - // -- a conversion-function-id that specifies a dependent type, - // -- a nested-name-specifier that contains a class-name that - // names a dependent type. - // Determine whether this is a member of an unknown specialization; - // we need to handle these differently. - bool DependentID = false; - if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName && - Name.getCXXNameType()->isDependentType()) { - DependentID = true; - } else if (SS.isSet()) { - if (DeclContext *DC = computeDeclContext(SS, false)) { - if (RequireCompleteDeclContext(SS, DC)) - return ExprError(); - } else { - DependentID = true; - } - } - - if (DependentID) - return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, - IsAddressOfOperand, TemplateArgs); - // BoundsSafety: This specially handles arguments of bounds attributes // appertains to a type of C struct field such that the name lookup // within a struct finds the member name, which is not the case for other @@ -2781,7 +2753,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, &AssumedTemplate)) return ExprError(); - if (R.wasNotFoundInCurrentInstantiation()) + if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid()) return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, IsAddressOfOperand, TemplateArgs); } else { @@ -2791,7 +2763,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // If the result might be in a dependent base class, this is a dependent // id-expression. - if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) + if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid()) return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, IsAddressOfOperand, TemplateArgs); @@ -2946,26 +2918,14 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, /// this path. ExprResult Sema::BuildQualifiedDeclarationNameExpr( CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, - bool IsAddressOfOperand, const Scope *S, TypeSourceInfo **RecoveryTSI) { - if (NameInfo.getName().isDependentName()) - return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - DeclContext *DC = computeDeclContext(SS, false); - if (!DC) - return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - if (RequireCompleteDeclContext(SS, DC)) - return ExprError(); - + bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI) { LookupResult R(*this, NameInfo, LookupOrdinaryName); - LookupQualifiedName(R, DC); + LookupParsedName(R, /*S=*/nullptr, &SS, /*ObjectType=*/QualType()); if (R.isAmbiguous()) return ExprError(); - if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) + if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid()) return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), NameInfo, /*TemplateArgs=*/nullptr); @@ -2974,6 +2934,7 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr( // diagnostic during template instantiation is likely bogus, e.g. if a class // is invalid because it's derived from an invalid base class, then missing // members were likely supposed to be inherited. + DeclContext *DC = computeDeclContext(SS); if (const auto *CD = dyn_cast(DC)) if (CD->isInvalidDecl()) return ExprError(); @@ -3017,16 +2978,14 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr( return ExprEmpty(); } - // Defend against this resolving to an implicit member access. We usually - // won't get here if this might be a legitimate a class member (we end up in - // BuildMemberReferenceExpr instead), but this can be valid if we're forming - // a pointer-to-member or in an unevaluated context in C++11. - if (!R.empty() && (*R.begin())->isCXXClassMember() && !IsAddressOfOperand) + // If necessary, build an implicit class member access. + if (isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand)) return BuildPossibleImplicitMemberExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - R, /*TemplateArgs=*/nullptr, S); + R, /*TemplateArgs=*/nullptr, + /*S=*/nullptr); - return BuildDeclarationNameExpr(SS, R, /* ADL */ false); + return BuildDeclarationNameExpr(SS, R, /*ADL=*/false); } /// Cast a base object to a member's actual type. @@ -3190,7 +3149,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, return false; // Never if a scope specifier was provided. - if (SS.isSet()) + if (SS.isNotEmpty()) return false; // Only in C++ or ObjC++. diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 0834db95d42a..e4d4cd7395eb 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -2771,9 +2771,6 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, ObjectType->castAs()->isBeingDefined()) && "Caller should have completed object type"); } else if (SS && SS->isNotEmpty()) { - if (NestedNameSpecifier *NNS = SS->getScopeRep(); - NNS->getKind() == NestedNameSpecifier::Super) - return LookupInSuper(R, NNS->getAsRecordDecl()); // This nested-name-specifier occurs after another nested-name-specifier, // so long into the context associated with the prior nested-name-specifier. if ((DC = computeDeclContext(*SS, EnteringContext))) { @@ -2781,6 +2778,12 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, if (!DC->isDependentContext() && RequireCompleteDeclContext(*SS, DC)) return false; R.setContextRange(SS->getRange()); + // FIXME: '__super' lookup semantics could be implemented by a + // LookupResult::isSuperLookup flag which skips the initial search of + // the lookup context in LookupQualified. + if (NestedNameSpecifier *NNS = SS->getScopeRep(); + NNS->getKind() == NestedNameSpecifier::Super) + return LookupInSuper(R, NNS->getAsRecordDecl()); } IsDependent = !DC && isDependentScopeSpecifier(*SS); } else { diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 8a7af678b33d..de884260790c 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -726,44 +726,22 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, bool isAddressOfOperand, const TemplateArgumentListInfo *TemplateArgs) { - DeclContext *DC = getFunctionLevelDeclContext(); - - // C++11 [expr.prim.general]p12: - // An id-expression that denotes a non-static data member or non-static - // member function of a class can only be used: - // (...) - // - if that id-expression denotes a non-static data member and it - // appears in an unevaluated operand. - // - // If this might be the case, form a DependentScopeDeclRefExpr instead of a - // CXXDependentScopeMemberExpr. The former can instantiate to either - // DeclRefExpr or MemberExpr depending on lookup results, while the latter is - // always a MemberExpr. - bool MightBeCxx11UnevalField = - getLangOpts().CPlusPlus11 && isUnevaluatedContext(); - - // Check if the nested name specifier is an enum type. - bool IsEnum = false; - if (NestedNameSpecifier *NNS = SS.getScopeRep()) - IsEnum = isa_and_nonnull(NNS->getAsType()); - - if (!MightBeCxx11UnevalField && !isAddressOfOperand && !IsEnum && - isa(DC) && - cast(DC)->isImplicitObjectMemberFunction()) { - QualType ThisType = - cast(DC)->getThisType().getNonReferenceType(); - - // Since the 'this' expression is synthesized, we don't need to - // perform the double-lookup check. - NamedDecl *FirstQualifierInScope = nullptr; + if (SS.isEmpty()) { + // FIXME: This codepath is only used by dependent unqualified names + // (e.g. a dependent conversion-function-id, or operator= once we support + // it). It doesn't quite do the right thing, and it will silently fail if + // getCurrentThisType() returns null. + QualType ThisType = getCurrentThisType(); + if (ThisType.isNull()) + return ExprError(); return CXXDependentScopeMemberExpr::Create( - Context, /*This=*/nullptr, ThisType, + Context, /*Base=*/nullptr, ThisType, /*IsArrow=*/!Context.getLangOpts().HLSL, - /*Op=*/SourceLocation(), SS.getWithLocInContext(Context), TemplateKWLoc, - FirstQualifierInScope, NameInfo, TemplateArgs); + /*OperatorLoc=*/SourceLocation(), + /*QualifierLoc=*/NestedNameSpecifierLoc(), TemplateKWLoc, + /*FirstQualifierFoundInScope=*/nullptr, NameInfo, TemplateArgs); } - return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); } @@ -772,13 +750,15 @@ Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs) { - // DependentScopeDeclRefExpr::Create requires a valid QualifierLoc - NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); - if (!QualifierLoc) - return ExprError(); + // DependentScopeDeclRefExpr::Create requires a valid NestedNameSpecifierLoc + if (!SS.isValid()) + return CreateRecoveryExpr( + SS.getBeginLoc(), + TemplateArgs ? TemplateArgs->getRAngleLoc() : NameInfo.getEndLoc(), {}); return DependentScopeDeclRefExpr::Create( - Context, QualifierLoc, TemplateKWLoc, NameInfo, TemplateArgs); + Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo, + TemplateArgs); } @@ -5747,50 +5727,36 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, } // We actually only call this from template instantiation. -ExprResult -Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs) { - +ExprResult Sema::BuildQualifiedTemplateIdExpr( + CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs, bool IsAddressOfOperand) { assert(TemplateArgs || TemplateKWLoc.isValid()); - DeclContext *DC; - if (!(DC = computeDeclContext(SS, false)) || - DC->isDependentContext() || - RequireCompleteDeclContext(SS, DC)) - return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); LookupResult R(*this, NameInfo, LookupOrdinaryName); - if (LookupTemplateName(R, (Scope *)nullptr, SS, QualType(), - /*Entering*/ false, TemplateKWLoc)) + if (LookupTemplateName(R, /*S=*/nullptr, SS, /*ObjectType=*/QualType(), + /*EnteringContext=*/false, TemplateKWLoc)) return ExprError(); if (R.isAmbiguous()) return ExprError(); + if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid()) + return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); + if (R.empty()) { + DeclContext *DC = computeDeclContext(SS); Diag(NameInfo.getLoc(), diag::err_no_member) << NameInfo.getName() << DC << SS.getRange(); return ExprError(); } - auto DiagnoseTypeTemplateDecl = [&](TemplateDecl *Temp, - bool isTypeAliasTemplateDecl) { - Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_type_template) - << SS.getScopeRep() << NameInfo.getName().getAsString() << SS.getRange() - << isTypeAliasTemplateDecl; - Diag(Temp->getLocation(), diag::note_referenced_type_template) - << isTypeAliasTemplateDecl; - return CreateRecoveryExpr(NameInfo.getBeginLoc(), NameInfo.getEndLoc(), {}); - }; - - if (ClassTemplateDecl *Temp = R.getAsSingle()) - return DiagnoseTypeTemplateDecl(Temp, false); - - if (TypeAliasTemplateDecl *Temp = R.getAsSingle()) - return DiagnoseTypeTemplateDecl(Temp, true); + // If necessary, build an implicit class member access. + if (isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand)) + return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, + /*S=*/nullptr); - return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/ false, TemplateArgs); + return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL=*/false, TemplateArgs); } /// Form a template name from a name that is syntactically required to name a @@ -5982,8 +5948,7 @@ bool Sema::CheckTemplateTypeArgument( LookupParsedName(Result, CurScope, &SS, /*ObjectType=*/QualType()); if (Result.getAsSingle() || - Result.getResultKind() == - LookupResult::NotFoundInCurrentInstantiation) { + Result.wasNotFoundInCurrentInstantiation()) { assert(SS.getScopeRep() && "dependent scope expr must has a scope!"); // Suggest that the user add 'typename' before the NNS. SourceLocation Loc = AL.getSourceRange().getBegin(); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index f9fec21bf5bb..d99bb2032060 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -3478,11 +3478,11 @@ public: SS.Adopt(QualifierLoc); if (TemplateArgs || TemplateKWLoc.isValid()) - return getSema().BuildQualifiedTemplateIdExpr(SS, TemplateKWLoc, NameInfo, - TemplateArgs); + return getSema().BuildQualifiedTemplateIdExpr( + SS, TemplateKWLoc, NameInfo, TemplateArgs, IsAddressOfOperand); return getSema().BuildQualifiedDeclarationNameExpr( - SS, NameInfo, IsAddressOfOperand, /*S*/nullptr, RecoveryTSI); + SS, NameInfo, IsAddressOfOperand, RecoveryTSI); } /// Build a new template-id expression. diff --git a/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp b/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp index 9116e7146f81..01fa923dd171 100644 --- a/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp +++ b/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp @@ -70,7 +70,7 @@ namespace test2 { } void test1() { - B::foo(); + B::foo(); // expected-error {{call to non-static member function without an object argument}} } static void test2() { @@ -91,8 +91,95 @@ namespace test2 { int test() { A a; a.test0(); // no instantiation note here, decl is ill-formed - a.test1(); + a.test1(); // expected-note {{in instantiation}} a.test2(); // expected-note {{in instantiation}} a.test3(); // expected-note {{in instantiation}} } } + +namespace test3 { + struct A { + void f0(); + + template + void f1(); + + static void f2(); + + template + static void f3(); + + int x0; + + static constexpr int x1 = 0; + + template + static constexpr int x2 = 0; + }; + + template + struct B : T { + auto g0() -> decltype(T::f0()); + + auto g1() -> decltype(T::template f1()); + + auto g2() -> decltype(T::f2()); + + auto g3() -> decltype(T::template f3()); + + auto g4() -> decltype(T::x0); + + auto g5() -> decltype(T::x1); + + auto g6() -> decltype(T::template x2); + + decltype(T::f0()) g7(); // expected-error {{call to non-static member function without an object argument}} + + decltype(T::template f1()) g8(); // expected-error {{call to non-static member function without an object argument}} + + decltype(T::f2()) g9(); + + decltype(T::template f3()) g10(); + + decltype(T::x0) g11(); + + decltype(T::x1) g12(); + + decltype(T::template x2) g13(); + }; + + template struct B; // expected-note {{in instantiation of}} + + template + struct C : T { + static auto g0() -> decltype(T::f0()); // expected-error {{'this' cannot be implicitly used in a static member function declaration}} + + static auto g1() -> decltype(T::template f1()); // expected-error {{'this' cannot be implicitly used in a static member function declaration}} + + static auto g2() -> decltype(T::f2()); + + static auto g3() -> decltype(T::template f3()); + + static auto g4() -> decltype(T::x0); // expected-error {{'this' cannot be implicitly used in a static member function declaration}} + + static auto g5() -> decltype(T::x1); + + static auto g6() -> decltype(T::template x2); + + static decltype(T::f0()) g7(); // expected-error {{call to non-static member function without an object argument}} + + static decltype(T::template f1()) g8(); // expected-error {{call to non-static member function without an object argument}} + + static decltype(T::f2()) g9(); + + static decltype(T::template f3()) g10(); + + static decltype(T::x0) g11(); + + static decltype(T::x1) g12(); + + static decltype(T::template x2) g13(); + }; + + template struct C; // expected-note {{in instantiation of}} +} diff --git a/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp b/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp index c49d2cb2422f..e1f3ab37ad94 100644 --- a/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp +++ b/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp @@ -464,6 +464,32 @@ namespace UsesThis { g1(x1); g1(y0); g1(y1); + + T::f0(0); + T::f0(z); + T::f0(x0); + T::f0(x1); + T::f0(y0); + T::f0(y1); + T::g0(0); + T::g0(z); + T::g0(x0); + T::g0(x1); + T::g0(y0); + T::g0(y1); + + E::f1(0); + E::f1(z); + E::f1(x0); + E::f1(x1); + E::f1(y0); + E::f1(y1); + E::g1(0); + E::g1(z); + E::g1(x0); + E::g1(x1); + E::g1(y0); + E::g1(y1); } template<> @@ -519,6 +545,32 @@ namespace UsesThis { g1(x1); // expected-error {{invalid use of member 'x1' in static member function}} g1(y0); g1(y1); + + T::f0(0); // expected-error {{call to non-static member function without an object argument}} + T::f0(z); // expected-error {{call to non-static member function without an object argument}} + T::f0(x0); // expected-error {{call to non-static member function without an object argument}} + T::f0(x1); // expected-error {{call to non-static member function without an object argument}} + T::f0(y0); // expected-error {{call to non-static member function without an object argument}} + T::f0(y1); // expected-error {{call to non-static member function without an object argument}} + T::g0(0); + T::g0(z); + T::g0(x0); // expected-error {{invalid use of member 'x0' in static member function}} + T::g0(x1); // expected-error {{invalid use of member 'x1' in static member function}} + T::g0(y0); + T::g0(y1); + + E::f1(0); // expected-error {{call to non-static member function without an object argument}} + E::f1(z); // expected-error {{call to non-static member function without an object argument}} + E::f1(x0); // expected-error {{call to non-static member function without an object argument}} + E::f1(x1); // expected-error {{call to non-static member function without an object argument}} + E::f1(y0); // expected-error {{call to non-static member function without an object argument}} + E::f1(y1); // expected-error {{call to non-static member function without an object argument}} + E::g1(0); + E::g1(z); + E::g1(x0); // expected-error {{invalid use of member 'x0' in static member function}} + E::g1(x1); // expected-error {{invalid use of member 'x1' in static member function}} + E::g1(y0); + E::g1(y1); } }; diff --git a/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp b/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp index 534a5dc9ddc1..547e5945ac6b 100644 --- a/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp +++ b/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp @@ -102,7 +102,7 @@ public: }; template class B; // expected-note {{requested here}} -} +} @@ -111,8 +111,8 @@ namespace lookup_dependent_base_class_default_argument { template class A { public: - static int f1(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} - int f2(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} + static int f1(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} + int f2(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} }; template @@ -137,7 +137,7 @@ namespace lookup_dependent_base_class_friend { template class B { public: - static void g(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} + static void g(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} }; template @@ -228,7 +228,7 @@ template struct C : T { int *bar() { return &b; } // expected-error {{no member named 'b' in 'PR16014::C'}} expected-warning {{lookup into dependent bases}} int baz() { return T::b; } // expected-error {{no member named 'b' in 'PR16014::A'}} int T::*qux() { return &T::b; } // expected-error {{no member named 'b' in 'PR16014::A'}} - int T::*fuz() { return &U::a; } // expected-error {{use of undeclared identifier 'U'}} \ + int T::*fuz() { return &U::a; } // expected-error {{no member named 'U' in 'PR16014::C'}} \ // expected-warning {{unqualified lookup into dependent bases of class template 'C'}} }; @@ -258,7 +258,7 @@ struct A : T { ::UndefClass::undef(); // expected-error {{no member named 'UndefClass' in the global namespace}} } void baz() { - B::qux(); // expected-error {{use of undeclared identifier 'B'}} \ + B::qux(); // expected-error {{no member named 'B' in 'PR19233::A'}} \ // expected-warning {{unqualified lookup into dependent bases of class template 'A'}} } }; diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index 65df513d2713..2e42b8580895 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -614,8 +614,10 @@ TEST_P(ASTMatchersTest, MemberExpr_MatchesVariable) { EXPECT_TRUE(matches("template " "class X : T { void f() { this->T::v; } };", cxxDependentScopeMemberExpr())); - EXPECT_TRUE(matches("template class X : T { void f() { T::v; } };", - cxxDependentScopeMemberExpr())); + // FIXME: Add a matcher for DependentScopeDeclRefExpr. + EXPECT_TRUE( + notMatches("template class X : T { void f() { T::v; } };", + cxxDependentScopeMemberExpr())); EXPECT_TRUE(matches("template void x() { T t; t.v; }", cxxDependentScopeMemberExpr())); } -- GitLab From c6486633d2656faecea8d7eb426bb22c52ddfd14 Mon Sep 17 00:00:00 2001 From: Yingchi Long Date: Tue, 21 May 2024 01:57:56 +0800 Subject: [PATCH 112/793] [BPF] report `Invalid usage of the XADD return value"` elegantly (#92742) Previously `report_fatal_error` is used for reporting something goes wrong in the backend, but this is confusing because `report_fatal_error` basically means there are something unexpected & crashed in the backend. So, turn this "crash" into an elegant error reporting. After this patch, clang can diagnose it: bpf-crash.c:4:30: error: Invalid usage of the XADD return value 4 | u32 next_event_id() { return __sync_fetch_and_add(&GLOBAL_EVENT_ID, 1); } | ^ 1 error generated. --- llvm/lib/Target/BPF/BPFMIChecking.cpp | 9 ++++----- llvm/test/CodeGen/BPF/xadd.ll | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Target/BPF/BPFMIChecking.cpp b/llvm/lib/Target/BPF/BPFMIChecking.cpp index 89ac485b1675..a968950f5bfc 100644 --- a/llvm/lib/Target/BPF/BPFMIChecking.cpp +++ b/llvm/lib/Target/BPF/BPFMIChecking.cpp @@ -20,6 +20,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/Support/Debug.h" using namespace llvm; @@ -164,11 +165,9 @@ bool BPFMIPreEmitChecking::processAtomicInsts() { if (hasLiveDefs(MI, TRI)) { DebugLoc Empty; const DebugLoc &DL = MI.getDebugLoc(); - if (DL != Empty) - report_fatal_error(Twine("line ") + std::to_string(DL.getLine()) + - ": Invalid usage of the XADD return value", false); - else - report_fatal_error("Invalid usage of the XADD return value", false); + const Function &F = MF->getFunction(); + F.getContext().diagnose(DiagnosticInfoUnsupported{ + F, "Invalid usage of the XADD return value", DL}); } } } diff --git a/llvm/test/CodeGen/BPF/xadd.ll b/llvm/test/CodeGen/BPF/xadd.ll index 4901d9380ac4..5aeeb9baf7b8 100644 --- a/llvm/test/CodeGen/BPF/xadd.ll +++ b/llvm/test/CodeGen/BPF/xadd.ll @@ -22,7 +22,7 @@ entry: call void @llvm.dbg.value(metadata ptr %ptr, metadata !13, metadata !DIExpression()), !dbg !15 %0 = atomicrmw add ptr %ptr, i32 4 seq_cst, !dbg !16 %1 = atomicrmw add ptr %ptr, i32 6 seq_cst, !dbg !17 -; CHECK: line 4: Invalid usage of the XADD return value +; CHECK: in function test i32 (ptr): Invalid usage of the XADD return value call void @llvm.dbg.value(metadata i32 %1, metadata !14, metadata !DIExpression()), !dbg !18 ret i32 %1, !dbg !19 } -- GitLab From 549fdda3e1e4e01acd6a11f3808d6500b4ded36c Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Mon, 20 May 2024 18:58:17 +0100 Subject: [PATCH 113/793] [AMDGPU] Refactor int_amdgcn_mov_dpp8 patterns. NFC. (#92764) I still don't see why we need to select to different Real instructions on different targets, but at least this is less verbose. --- llvm/lib/Target/AMDGPU/VOP1Instructions.td | 40 ++++------------------ 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/VOP1Instructions.td b/llvm/lib/Target/AMDGPU/VOP1Instructions.td index b875ddc62a7a..586a4a74ec34 100644 --- a/llvm/lib/Target/AMDGPU/VOP1Instructions.td +++ b/llvm/lib/Target/AMDGPU/VOP1Instructions.td @@ -1431,38 +1431,12 @@ defm V_CVT_F32_BF8 : VOP1_Real_NoDstSel_SDWA_gfx9<0x55>; defm V_CVT_PK_F32_FP8 : VOP1_Real_NoDstSel_SDWA_gfx9<0x56>; defm V_CVT_PK_F32_BF8 : VOP1_Real_NoDstSel_SDWA_gfx9<0x57>; -//===----------------------------------------------------------------------===// -// GFX10 -//===----------------------------------------------------------------------===// - -let OtherPredicates = [isGFX10Only] in { -def : GCNPat < +class MovDPP8Pattern : GCNPat < (i32 (int_amdgcn_mov_dpp8 i32:$src, timm:$dpp8)), - (V_MOV_B32_dpp8_gfx10 VGPR_32:$src, VGPR_32:$src, - (as_i32timm $dpp8), (i32 DPP8Mode.FI_0)) ->; -} // End OtherPredicates = [isGFX10Only] - -//===----------------------------------------------------------------------===// -// GFX11 -//===----------------------------------------------------------------------===// - -let OtherPredicates = [isGFX11Only] in { -def : GCNPat < - (i32 (int_amdgcn_mov_dpp8 i32:$src, timm:$dpp8)), - (V_MOV_B32_dpp8_gfx11 VGPR_32:$src, VGPR_32:$src, - (as_i32timm $dpp8), (i32 DPP8Mode.FI_0)) ->; -} // End OtherPredicates = [isGFX11Only] - -//===----------------------------------------------------------------------===// -// GFX12 -//===----------------------------------------------------------------------===// + (Inst VGPR_32:$src, VGPR_32:$src, (as_i32timm $dpp8), (i32 DPP8Mode.FI_0))> { + let OtherPredicates = [Pred]; +} -let OtherPredicates = [isGFX12Only] in { -def : GCNPat < - (i32 (int_amdgcn_mov_dpp8 i32:$src, timm:$dpp8)), - (V_MOV_B32_dpp8_gfx12 VGPR_32:$src, VGPR_32:$src, - (as_i32timm $dpp8), (i32 DPP8Mode.FI_0)) ->; -} // End OtherPredicates = [isGFX12Only] +def : MovDPP8Pattern; +def : MovDPP8Pattern; +def : MovDPP8Pattern; -- GitLab From 3591da9f1ccbd8b19fef4814f96638dbbe9c2b40 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Mon, 20 May 2024 14:23:17 -0400 Subject: [PATCH 114/793] Fix test for non-Itanium ABIs. This amends 702a2b627ff4b2a5d330a7bd0d3f7cadaff0b4ed to hopefully get the test passing for Windows again. --- clang/test/CoverageMapping/mcdc-system-headers.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/CoverageMapping/mcdc-system-headers.cpp b/clang/test/CoverageMapping/mcdc-system-headers.cpp index a8a3ddbb506f..4dfbb17c2bba 100644 --- a/clang/test/CoverageMapping/mcdc-system-headers.cpp +++ b/clang/test/CoverageMapping/mcdc-system-headers.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -fcoverage-mcdc -mllvm -system-headers-coverage -emit-llvm-only -o - %s | FileCheck %s --check-prefixes=CHECK,W_SYS -// RUN: %clang_cc1 -std=c++11 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -fcoverage-mcdc -emit-llvm-only -o - %s | FileCheck %s --check-prefixes=CHECK,X_SYS +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -fcoverage-mcdc -mllvm -system-headers-coverage -emit-llvm-only -o - %s | FileCheck %s --check-prefixes=CHECK,W_SYS +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -fcoverage-mcdc -emit-llvm-only -o - %s | FileCheck %s --check-prefixes=CHECK,X_SYS #ifdef IS_SYSHEADER -- GitLab From 245491a9f384e4c53421196533c2a2b693efaf8d Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 20 May 2024 11:31:56 -0700 Subject: [PATCH 115/793] [MC] Disable MCAssembler based constant folding for DwarfDebug Related to the poor performance of MCAssembler based constant folding (see `bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const` and `AttemptToFoldSymbolOffsetDifference`), commit 9500a5d02e23f9b43294e5f662ac099f8989c0e4 (#91082) caused -O0 -g compile time regression. 9500a5d02e23f9b43294e5f662ac099f8989c0e4 special cased .eh_frame FDE emitting. This patch adds a special case to .debug_* emitting as well to mitigate the rest regression. The MCAssembler based constant folding strategy should be improved to remove the two special cases. --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index d50cdc4323ec..c5755b9bdc8d 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2463,11 +2463,15 @@ bool AsmPrinter::doFinalization(Module &M) { emitGlobalIFunc(M, IFunc); // Finalize debug and EH information. + // Defer MCAssembler based constant folding due to a performance issue. The + // label differences will be evaluated at write time. + OutStreamer->setUseAssemblerInfoForParsing(false); for (const HandlerInfo &HI : Handlers) { NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName, HI.TimerGroupDescription, TimePassesIsEnabled); HI.Handler->endModule(); } + OutStreamer->setUseAssemblerInfoForParsing(true); // This deletes all the ephemeral handlers that AsmPrinter added, while // keeping all the user-added handlers alive until the AsmPrinter is -- GitLab From bce3680f45b57f6ce745cb7da659f2ece745a1d1 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Mon, 20 May 2024 19:29:16 +0100 Subject: [PATCH 116/793] [LAA] Move logic to compute start and end of a pointer to helper (NFC). This allows use at other places, in particular an updated version of https://github.com/llvm/llvm-project/pull/92307. --- llvm/lib/Analysis/LoopAccessAnalysis.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp index 13dec3b1e1b0..df01ad119a8b 100644 --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -203,11 +203,9 @@ RuntimeCheckingPtrGroup::RuntimeCheckingPtrGroup( /// /// There is no conflict when the intervals are disjoint: /// NoConflict = (P2.Start >= P1.End) || (P1.Start >= P2.End) -void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, const SCEV *PtrExpr, - Type *AccessTy, bool WritePtr, - unsigned DepSetId, unsigned ASId, - PredicatedScalarEvolution &PSE, - bool NeedsFreeze) { +static std::pair +getStartAndEndForAccess(const Loop *Lp, const SCEV *PtrExpr, Type *AccessTy, + PredicatedScalarEvolution &PSE) { ScalarEvolution *SE = PSE.getSE(); const SCEV *ScStart; @@ -242,10 +240,22 @@ void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, const SCEV *PtrExpr, // Add the size of the pointed element to ScEnd. auto &DL = Lp->getHeader()->getModule()->getDataLayout(); - Type *IdxTy = DL.getIndexType(Ptr->getType()); + Type *IdxTy = DL.getIndexType(PtrExpr->getType()); const SCEV *EltSizeSCEV = SE->getStoreSizeOfExpr(IdxTy, AccessTy); ScEnd = SE->getAddExpr(ScEnd, EltSizeSCEV); + return {ScStart, ScEnd}; +} + +/// Calculate Start and End points of memory access using +/// getStartAndEndForAccess. +void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, const SCEV *PtrExpr, + Type *AccessTy, bool WritePtr, + unsigned DepSetId, unsigned ASId, + PredicatedScalarEvolution &PSE, + bool NeedsFreeze) { + const auto &[ScStart, ScEnd] = + getStartAndEndForAccess(Lp, PtrExpr, AccessTy, PSE); Pointers.emplace_back(Ptr, ScStart, ScEnd, WritePtr, DepSetId, ASId, PtrExpr, NeedsFreeze); } -- GitLab From acf5ad2a4ed9bf94b03d18ccddce7710e721dc6c Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 20 May 2024 14:44:59 -0400 Subject: [PATCH 117/793] [Clang][Sema] Diagnose current instantiation used as an incomplete base class (#92597) Consider the following: ``` template struct A { struct B : A { }; }; ``` According to [class.derived.general] p2: > [...] A _class-or-decltype_ shall denote a (possibly cv-qualified) class type that is not an incompletely defined class; any cv-qualifiers are ignored. [...] Although GCC and EDG rejects this, Clang accepts it. This is incorrect, as `A` is incomplete within its own definition (outside of a complete-class context). This patch correctly diagnoses instances where the current instantiation is used as a base class before it is complete. Conversely, Clang erroneously rejects the following: ``` template struct A { struct B; struct C : B { }; struct B : C { }; // error: circular inheritance between 'C' and 'A::B' }; ``` Though it may seem like no valid specialization of this template can be instantiated, an explicit specialization of either member classes for an implicit instantiated specialization of `A` would permit the definition of the other member class to be instantiated, e.g.: ``` template<> struct A::B { }; A::C c; // ok ``` So this patch also does away with this error. This means that circular inheritance is diagnosed during instantiation of the definition as a consequence of requiring the base class type to be complete (matching the behavior of GCC and EDG). --- .../pro-type-member-init-no-crash.cpp | 8 + .../pro-type-member-init.cpp | 6 - clang/docs/ReleaseNotes.rst | 1 + .../clang/Basic/DiagnosticSemaKinds.td | 2 - clang/lib/AST/Type.cpp | 8 + clang/lib/Sema/SemaDeclCXX.cpp | 249 +++++++----------- .../basic.lookup.qual/class.qual/p2.cpp | 10 +- .../class.derived.general/p2.cpp | 116 ++++++++ clang/test/SemaTemplate/dependent-names.cpp | 14 +- .../test/SemaTemplate/destructor-template.cpp | 14 +- .../test/SemaTemplate/typo-dependent-name.cpp | 7 +- 11 files changed, 256 insertions(+), 179 deletions(-) create mode 100644 clang/test/CXX/class.derived/class.derived.general/p2.cpp diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init-no-crash.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init-no-crash.cpp index 300fff6cb179..2e2964dda1da 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init-no-crash.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init-no-crash.cpp @@ -5,3 +5,11 @@ struct X { // CHECK-MESSAGES: :[[@LINE-1]]:5: error: field has incomplete type 'X' [clang-diagnostic-error] int a = 10; }; + +template class NoCrash { + // CHECK-MESSAGES: :[[@LINE+2]]:20: error: base class has incomplete type + // CHECK-MESSAGES: :[[@LINE-2]]:29: note: definition of 'NoCrash' is not complete until the closing '}' + class B : public NoCrash { + template B(U u) {} + }; +}; diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init.cpp index 8d6992afef08..eaa73b906ce0 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init.cpp @@ -463,12 +463,6 @@ struct NegativeIncompleteArrayMember { char e[]; }; -template class NoCrash { - class B : public NoCrash { - template B(U u) {} - }; -}; - struct PositiveBitfieldMember { PositiveBitfieldMember() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ba4637d98197..88616b5bee73 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -746,6 +746,7 @@ Bug Fixes to C++ Support the ``constexpr`` specifier. Fixes (#GH61004). - Clang no longer transforms dependent qualified names into implicit class member access expressions until it can be determined whether the name is that of a non-static member. +- Clang now correctly diagnoses when the current instantiation is used as an incomplete base class. Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e3b4186f1b06..e3c65cba4886 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9464,8 +9464,6 @@ def err_static_data_member_not_allowed_in_local_class : Error< def err_base_clause_on_union : Error<"unions cannot have base classes">; def err_base_must_be_class : Error<"base specifier must name a class">; def err_union_as_base_class : Error<"unions cannot be base classes">; -def err_circular_inheritance : Error< - "circular inheritance between %0 and %1">; def err_base_class_has_flexible_array_member : Error< "base class %0 has a flexible array member">; def err_incomplete_base_class : Error<"base class has incomplete type">; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index e31741cd4424..3b90b8229dd1 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2372,6 +2372,14 @@ bool Type::isIncompleteType(NamedDecl **Def) const { *Def = Rec; return !Rec->isCompleteDefinition(); } + case InjectedClassName: { + CXXRecordDecl *Rec = cast(CanonicalType)->getDecl(); + if (!Rec->isBeingDefined()) + return false; + if (Def) + *Def = Rec; + return true; + } case ConstantArray: case VariableArray: // An array is incomplete if its element type is incomplete diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 822538198505..104e27139fe4 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2656,188 +2656,122 @@ bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) { return false; } -/// Determine whether the given class is a base class of the given -/// class, including looking at dependent bases. -static bool findCircularInheritance(const CXXRecordDecl *Class, - const CXXRecordDecl *Current) { - SmallVector Queue; - - Class = Class->getCanonicalDecl(); - while (true) { - for (const auto &I : Current->bases()) { - CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl(); - if (!Base) - continue; - - Base = Base->getDefinition(); - if (!Base) - continue; - - if (Base->getCanonicalDecl() == Class) - return true; - - Queue.push_back(Base); - } - - if (Queue.empty()) - return false; - - Current = Queue.pop_back_val(); - } - - return false; -} - /// Check the validity of a C++ base class specifier. /// /// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics /// and returns NULL otherwise. -CXXBaseSpecifier * -Sema::CheckBaseSpecifier(CXXRecordDecl *Class, - SourceRange SpecifierRange, - bool Virtual, AccessSpecifier Access, - TypeSourceInfo *TInfo, - SourceLocation EllipsisLoc) { - // In HLSL, unspecified class access is public rather than private. - if (getLangOpts().HLSL && Class->getTagKind() == TagTypeKind::Class && - Access == AS_none) - Access = AS_public; - +CXXBaseSpecifier *Sema::CheckBaseSpecifier(CXXRecordDecl *Class, + SourceRange SpecifierRange, + bool Virtual, AccessSpecifier Access, + TypeSourceInfo *TInfo, + SourceLocation EllipsisLoc) { QualType BaseType = TInfo->getType(); + SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); if (BaseType->containsErrors()) { // Already emitted a diagnostic when parsing the error type. return nullptr; } - // C++ [class.union]p1: - // A union shall not have base classes. - if (Class->isUnion()) { - Diag(Class->getLocation(), diag::err_base_clause_on_union) - << SpecifierRange; - return nullptr; - } - if (EllipsisLoc.isValid() && - !TInfo->getType()->containsUnexpandedParameterPack()) { + if (EllipsisLoc.isValid() && !BaseType->containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << TInfo->getTypeLoc().getSourceRange(); EllipsisLoc = SourceLocation(); } - SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); - - if (BaseType->isDependentType()) { - // Make sure that we don't have circular inheritance among our dependent - // bases. For non-dependent bases, the check for completeness below handles - // this. - if (CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl()) { - if (BaseDecl->getCanonicalDecl() == Class->getCanonicalDecl() || - ((BaseDecl = BaseDecl->getDefinition()) && - findCircularInheritance(Class, BaseDecl))) { - Diag(BaseLoc, diag::err_circular_inheritance) - << BaseType << Context.getTypeDeclType(Class); - - if (BaseDecl->getCanonicalDecl() != Class->getCanonicalDecl()) - Diag(BaseDecl->getLocation(), diag::note_previous_decl) - << BaseType; + auto *BaseDecl = + dyn_cast_if_present(computeDeclContext(BaseType)); + // C++ [class.derived.general]p2: + // A class-or-decltype shall denote a (possibly cv-qualified) class type + // that is not an incompletely defined class; any cv-qualifiers are + // ignored. + if (BaseDecl) { + // C++ [class.union.general]p4: + // [...] A union shall not be used as a base class. + if (BaseDecl->isUnion()) { + Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; + return nullptr; + } - return nullptr; + // For the MS ABI, propagate DLL attributes to base class templates. + if (Context.getTargetInfo().getCXXABI().isMicrosoft() || + Context.getTargetInfo().getTriple().isPS()) { + if (Attr *ClassAttr = getDLLAttr(Class)) { + if (auto *BaseSpec = + dyn_cast(BaseDecl)) { + propagateDLLAttrToBaseClassTemplate(Class, ClassAttr, BaseSpec, + BaseLoc); + } } } + if (RequireCompleteType(BaseLoc, BaseType, diag::err_incomplete_base_class, + SpecifierRange)) { + Class->setInvalidDecl(); + return nullptr; + } + + BaseDecl = BaseDecl->getDefinition(); + assert(BaseDecl && "Base type is not incomplete, but has no definition"); + + // Microsoft docs say: + // "If a base-class has a code_seg attribute, derived classes must have the + // same attribute." + const auto *BaseCSA = BaseDecl->getAttr(); + const auto *DerivedCSA = Class->getAttr(); + if ((DerivedCSA || BaseCSA) && + (!BaseCSA || !DerivedCSA || + BaseCSA->getName() != DerivedCSA->getName())) { + Diag(Class->getLocation(), diag::err_mismatched_code_seg_base); + Diag(BaseDecl->getLocation(), diag::note_base_class_specified_here) + << BaseDecl; + return nullptr; + } + + // A class which contains a flexible array member is not suitable for use as + // a base class: + // - If the layout determines that a base comes before another base, + // the flexible array member would index into the subsequent base. + // - If the layout determines that base comes before the derived class, + // the flexible array member would index into the derived class. + if (BaseDecl->hasFlexibleArrayMember()) { + Diag(BaseLoc, diag::err_base_class_has_flexible_array_member) + << BaseDecl->getDeclName(); + return nullptr; + } + + // C++ [class]p3: + // If a class is marked final and it appears as a base-type-specifier in + // base-clause, the program is ill-formed. + if (FinalAttr *FA = BaseDecl->getAttr()) { + Diag(BaseLoc, diag::err_class_marked_final_used_as_base) + << BaseDecl->getDeclName() << FA->isSpelledAsSealed(); + Diag(BaseDecl->getLocation(), diag::note_entity_declared_at) + << BaseDecl->getDeclName() << FA->getRange(); + return nullptr; + } + + // If the base class is invalid the derived class is as well. + if (BaseDecl->isInvalidDecl()) + Class->setInvalidDecl(); + } else if (BaseType->isDependentType()) { // Make sure that we don't make an ill-formed AST where the type of the // Class is non-dependent and its attached base class specifier is an // dependent type, which violates invariants in many clang code paths (e.g. // constexpr evaluator). If this case happens (in errory-recovery mode), we // explicitly mark the Class decl invalid. The diagnostic was already // emitted. - if (!Class->getTypeForDecl()->isDependentType()) + if (!Class->isDependentContext()) Class->setInvalidDecl(); - return new (Context) CXXBaseSpecifier( - SpecifierRange, Virtual, Class->getTagKind() == TagTypeKind::Class, - Access, TInfo, EllipsisLoc); - } - - // Base specifiers must be record types. - if (!BaseType->isRecordType()) { + } else { + // The base class is some non-dependent non-class type. Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange; return nullptr; } - // C++ [class.union]p1: - // A union shall not be used as a base class. - if (BaseType->isUnionType()) { - Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; - return nullptr; - } - - // For the MS ABI, propagate DLL attributes to base class templates. - if (Context.getTargetInfo().getCXXABI().isMicrosoft() || - Context.getTargetInfo().getTriple().isPS()) { - if (Attr *ClassAttr = getDLLAttr(Class)) { - if (auto *BaseTemplate = dyn_cast_or_null( - BaseType->getAsCXXRecordDecl())) { - propagateDLLAttrToBaseClassTemplate(Class, ClassAttr, BaseTemplate, - BaseLoc); - } - } - } - - // C++ [class.derived]p2: - // The class-name in a base-specifier shall not be an incompletely - // defined class. - if (RequireCompleteType(BaseLoc, BaseType, - diag::err_incomplete_base_class, SpecifierRange)) { - Class->setInvalidDecl(); - return nullptr; - } - - // If the base class is polymorphic or isn't empty, the new one is/isn't, too. - RecordDecl *BaseDecl = BaseType->castAs()->getDecl(); - assert(BaseDecl && "Record type has no declaration"); - BaseDecl = BaseDecl->getDefinition(); - assert(BaseDecl && "Base type is not incomplete, but has no definition"); - CXXRecordDecl *CXXBaseDecl = cast(BaseDecl); - assert(CXXBaseDecl && "Base type is not a C++ type"); - - // Microsoft docs say: - // "If a base-class has a code_seg attribute, derived classes must have the - // same attribute." - const auto *BaseCSA = CXXBaseDecl->getAttr(); - const auto *DerivedCSA = Class->getAttr(); - if ((DerivedCSA || BaseCSA) && - (!BaseCSA || !DerivedCSA || BaseCSA->getName() != DerivedCSA->getName())) { - Diag(Class->getLocation(), diag::err_mismatched_code_seg_base); - Diag(CXXBaseDecl->getLocation(), diag::note_base_class_specified_here) - << CXXBaseDecl; - return nullptr; - } - - // A class which contains a flexible array member is not suitable for use as a - // base class: - // - If the layout determines that a base comes before another base, - // the flexible array member would index into the subsequent base. - // - If the layout determines that base comes before the derived class, - // the flexible array member would index into the derived class. - if (CXXBaseDecl->hasFlexibleArrayMember()) { - Diag(BaseLoc, diag::err_base_class_has_flexible_array_member) - << CXXBaseDecl->getDeclName(); - return nullptr; - } - - // C++ [class]p3: - // If a class is marked final and it appears as a base-type-specifier in - // base-clause, the program is ill-formed. - if (FinalAttr *FA = CXXBaseDecl->getAttr()) { - Diag(BaseLoc, diag::err_class_marked_final_used_as_base) - << CXXBaseDecl->getDeclName() - << FA->isSpelledAsSealed(); - Diag(CXXBaseDecl->getLocation(), diag::note_entity_declared_at) - << CXXBaseDecl->getDeclName() << FA->getRange(); - return nullptr; - } - - if (BaseDecl->isInvalidDecl()) - Class->setInvalidDecl(); + // In HLSL, unspecified class access is public rather than private. + if (getLangOpts().HLSL && Class->getTagKind() == TagTypeKind::Class && + Access == AS_none) + Access = AS_public; // Create the base specifier. return new (Context) CXXBaseSpecifier( @@ -2887,13 +2821,20 @@ BaseResult Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, UPPC_BaseType)) return true; + // C++ [class.union.general]p4: + // [...] A union shall not have base classes. + if (Class->isUnion()) { + Diag(Class->getLocation(), diag::err_base_clause_on_union) + << SpecifierRange; + return true; + } + if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange, Virtual, Access, TInfo, EllipsisLoc)) return BaseSpec; - else - Class->setInvalidDecl(); + Class->setInvalidDecl(); return true; } diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp index be07ab0a48b3..0fa98ad101f6 100644 --- a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp @@ -141,11 +141,15 @@ namespace InhCtor { // ill-formed. template struct S : T { - struct U : S { // expected-note 6{{candidate}} - using S::S; - }; + struct U; // expected-note 6{{candidate}} using T::T; }; + + template + struct S::U : S { + using S::S; + }; + S::U ua(0); // expected-error {{no match}} S::U ub(0); // expected-error {{no match}} diff --git a/clang/test/CXX/class.derived/class.derived.general/p2.cpp b/clang/test/CXX/class.derived/class.derived.general/p2.cpp new file mode 100644 index 000000000000..888d9cd7a939 --- /dev/null +++ b/clang/test/CXX/class.derived/class.derived.general/p2.cpp @@ -0,0 +1,116 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify + +namespace CurrentInstantiation { + template + struct A0 { // expected-note 6{{definition of 'A0' is not complete until the closing '}'}} + struct B0 : A0 { }; // expected-error {{base class has incomplete type}} + + template + struct B1 : A0 { }; // expected-error {{base class has incomplete type}} + + struct B2; + + template + struct B3; + + struct B4 { // expected-note 2{{definition of 'CurrentInstantiation::A0::B4' is not complete until the closing '}'}} + struct C0 : A0, B4 { }; // expected-error 2{{base class has incomplete type}} + + template + struct C1 : A0, B4 { }; // expected-error 2{{base class has incomplete type}} + + struct C2; + + template + struct C3; + }; + + template + struct B5 { // expected-note 2{{definition of 'B5' is not complete until the closing '}'}} + struct C0 : A0, B5 { }; // expected-error 2{{base class has incomplete type}} + + template + struct C1 : A0, B5 { }; // expected-error 2{{base class has incomplete type}} + + struct C2; + + template + struct C3; + }; + }; + + template + struct A0::B2 : A0 { }; + + template + template + struct A0::B3 : A0 { }; + + template + struct A0::B4::C2 : A0, B4 { }; + + template + template + struct A0::B4::C3 : A0, B4 { }; + + template + template + struct A0::B5::C2 : A0, B5 { }; + + template + template + template + struct A0::B5::C3 : A0, B5 { }; + + template + struct A0 { // expected-note 2{{definition of 'A0' is not complete until the closing '}'}} + struct B0 : A0 { }; // expected-error {{base class has incomplete type}} + + template + struct B1 : A0 { }; // expected-error {{base class has incomplete type}} + + struct B2; + + template + struct B3; + }; + + template + struct A0::B2 : A0 { }; + + template + template + struct A0::B3 : A0 { }; +} // namespace CurrentInstantiation + +namespace MemberOfCurrentInstantiation { + template + struct A0 { + struct B : B { }; // expected-error {{base class has incomplete type}} + // expected-note@-1 {{definition of 'MemberOfCurrentInstantiation::A0::B' is not complete until the closing '}'}} + + template + struct C : C { }; // expected-error {{base class has incomplete type}} + // expected-note@-1 {{definition of 'C' is not complete until the closing '}'}} + }; + + template + struct A1 { + struct B; // expected-note {{definition of 'MemberOfCurrentInstantiation::A1::B' is not complete until the closing '}'}} + + struct C : B { }; // expected-error {{base class has incomplete type}} + + struct B : C { }; // expected-note {{in instantiation of member class 'MemberOfCurrentInstantiation::A1::C' requested here}} + }; + + template struct A1; // expected-note {{in instantiation of member class 'MemberOfCurrentInstantiation::A1::B' requested here}} + + template<> + struct A1::B { + static constexpr bool f() { + return true; + } + }; + + static_assert(A1::C::f()); +} // namespace MemberOfCurrentInstantiation diff --git a/clang/test/SemaTemplate/dependent-names.cpp b/clang/test/SemaTemplate/dependent-names.cpp index 641ec950054f..a7260b194462 100644 --- a/clang/test/SemaTemplate/dependent-names.cpp +++ b/clang/test/SemaTemplate/dependent-names.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s typedef double A; template class B { @@ -334,8 +334,9 @@ int arr[sizeof(Sub)]; namespace PR11421 { template < unsigned > struct X { static const unsigned dimension = 3; - template - struct Y: Y { }; // expected-error{{circular inheritance between 'Y' and 'Y'}} + template + struct Y: Y { }; // expected-error{{base class has incomplete type}} + // expected-note@-1{{definition of 'Y' is not complete until the closing '}'}} }; typedef X<3> X3; X3::Y<>::iterator it; // expected-error {{no type named 'iterator' in 'PR11421::X<3>::Y<>'}} @@ -344,11 +345,12 @@ X3::Y<>::iterator it; // expected-error {{no type named 'iterator' in 'PR11421:: namespace rdar12629723 { template struct X { - struct C : public C { }; // expected-error{{circular inheritance between 'C' and 'rdar12629723::X::C'}} + struct C : public C { }; // expected-error{{base class has incomplete type}} + // expected-note@-1{{definition of 'rdar12629723::X::C' is not complete until the closing '}'}} struct B; - struct A : public B { // expected-note{{'A' declared here}} + struct A : public B { virtual void foo() { } }; @@ -357,7 +359,7 @@ namespace rdar12629723 { }; template - struct X::B : public A { // expected-error{{circular inheritance between 'A' and 'rdar12629723::X::B'}} + struct X::B : public A { virtual void foo() { } }; } diff --git a/clang/test/SemaTemplate/destructor-template.cpp b/clang/test/SemaTemplate/destructor-template.cpp index 890188294762..7a3398308bbe 100644 --- a/clang/test/SemaTemplate/destructor-template.cpp +++ b/clang/test/SemaTemplate/destructor-template.cpp @@ -1,12 +1,14 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s template class s0 { + template class s1; +}; - template class s1 : public s0 { - ~s1() {} - s0 ms0; - }; - +template +template +class s0::s1 : s0 { + ~s1() {} + s0 ms0; }; struct Incomplete; @@ -28,7 +30,7 @@ namespace PR6152 { y->template Y::~Y(); y->~Y(); } - + template struct X; } diff --git a/clang/test/SemaTemplate/typo-dependent-name.cpp b/clang/test/SemaTemplate/typo-dependent-name.cpp index fb61b03e5010..5bd924241480 100644 --- a/clang/test/SemaTemplate/typo-dependent-name.cpp +++ b/clang/test/SemaTemplate/typo-dependent-name.cpp @@ -31,8 +31,7 @@ struct Y { static int z; template - struct Inner : Y { // expected-note {{declared here}} - }; + struct Inner; // expected-note {{declared here}} bool f(T other) { // We can determine that 'inner' does not exist at parse time, so can @@ -41,5 +40,9 @@ struct Y { } }; +template +template +struct Y::Inner : Y { }; + struct Q { constexpr operator int() { return 0; } }; void use_y(Y x) { x.f(Q()); } -- GitLab From a91d5c07f2357f10a5378bb3b0e439847f2b8e00 Mon Sep 17 00:00:00 2001 From: Kiran Chandramohan Date: Mon, 20 May 2024 19:47:50 +0100 Subject: [PATCH 118/793] [Flang][OpenMP] Disable all OpenMP semantics tests on Windows (#92739) Removes two XFAILed tests, the other tests are marked UNSUPPORTED only on windows. --- .../Semantics/OpenMP/allocate-clause01.f90 | 2 ++ .../Semantics/OpenMP/allocate-directive.f90 | 2 ++ flang/test/Semantics/OpenMP/allocate01.f90 | 2 ++ flang/test/Semantics/OpenMP/allocate02.f90 | 2 ++ flang/test/Semantics/OpenMP/allocate03.f90 | 2 ++ flang/test/Semantics/OpenMP/allocate04.f90 | 2 ++ flang/test/Semantics/OpenMP/allocate05.f90 | 2 ++ flang/test/Semantics/OpenMP/allocate06.f90 | 2 ++ flang/test/Semantics/OpenMP/allocate07.f90 | 2 ++ flang/test/Semantics/OpenMP/allocate08.f90 | 2 ++ flang/test/Semantics/OpenMP/allocate09.f90 | 2 ++ flang/test/Semantics/OpenMP/allocators01.f90 | 2 ++ flang/test/Semantics/OpenMP/allocators02.f90 | 2 ++ flang/test/Semantics/OpenMP/allocators03.f90 | 2 ++ flang/test/Semantics/OpenMP/allocators04.f90 | 2 ++ flang/test/Semantics/OpenMP/allocators05.f90 | 2 ++ flang/test/Semantics/OpenMP/allocators06.f90 | 2 ++ .../Semantics/OpenMP/atomic-hint-clause.f90 | 2 ++ flang/test/Semantics/OpenMP/atomic.f90 | 2 ++ flang/test/Semantics/OpenMP/atomic01.f90 | 2 ++ flang/test/Semantics/OpenMP/atomic02.f90 | 2 ++ flang/test/Semantics/OpenMP/atomic03.f90 | 2 ++ flang/test/Semantics/OpenMP/atomic04.f90 | 2 ++ flang/test/Semantics/OpenMP/atomic05.f90 | 2 ++ flang/test/Semantics/OpenMP/barrier.f90 | 2 ++ .../Semantics/OpenMP/clause-validity01.f90 | 2 ++ .../Semantics/OpenMP/combined-constructs.f90 | 2 ++ flang/test/Semantics/OpenMP/common-block.f90 | 2 ++ .../Semantics/OpenMP/compiler-directive.f90 | 2 ++ flang/test/Semantics/OpenMP/copyin01.f90 | 2 ++ flang/test/Semantics/OpenMP/copyin02.f90 | 2 ++ flang/test/Semantics/OpenMP/copyin03.f90 | 2 ++ flang/test/Semantics/OpenMP/copyin04.f90 | 2 ++ flang/test/Semantics/OpenMP/copyin05.f90 | 2 ++ flang/test/Semantics/OpenMP/copying.f90 | 2 ++ flang/test/Semantics/OpenMP/copyprivate01.f90 | 2 ++ flang/test/Semantics/OpenMP/copyprivate02.f90 | 2 ++ flang/test/Semantics/OpenMP/copyprivate03.f90 | 2 ++ .../test/Semantics/OpenMP/critical-empty.f90 | 2 ++ .../Semantics/OpenMP/critical-hint-clause.f90 | 2 ++ flang/test/Semantics/OpenMP/dealloc.f90 | 2 ++ .../OpenMP/declarative-directive.f90 | 2 ++ .../OpenMP/declare-target-common-block.f90 | 2 ++ .../Semantics/OpenMP/declare-target01.f90 | 2 ++ .../Semantics/OpenMP/declare-target02.f90 | 2 ++ .../Semantics/OpenMP/declare-target03.f90 | 2 ++ .../Semantics/OpenMP/declare-target04.f90 | 2 ++ .../Semantics/OpenMP/declare-target05.f90 | 2 ++ .../Semantics/OpenMP/declare-target06.f90 | 2 ++ .../Semantics/OpenMP/declare-target07.f90 | 2 ++ .../test/Semantics/OpenMP/default-clause.f90 | 2 ++ flang/test/Semantics/OpenMP/default-none.f90 | 2 ++ flang/test/Semantics/OpenMP/default.f90 | 2 ++ flang/test/Semantics/OpenMP/default02.f90 | 2 ++ flang/test/Semantics/OpenMP/depend01.f90 | 2 ++ flang/test/Semantics/OpenMP/depend02.f90 | 2 ++ flang/test/Semantics/OpenMP/depend03.f90 | 2 ++ .../test/Semantics/OpenMP/device-clause01.f90 | 2 ++ .../Semantics/OpenMP/device-constructs.f90 | 2 ++ .../OpenMP/do-collapse-positivecases.f90 | 2 ++ flang/test/Semantics/OpenMP/do-collapse.f90 | 2 ++ flang/test/Semantics/OpenMP/do-cycle.f90 | 2 ++ .../OpenMP/do-ordered-positivecases.f90 | 2 ++ flang/test/Semantics/OpenMP/do-ordered.f90 | 2 ++ flang/test/Semantics/OpenMP/do-schedule01.f90 | 2 ++ flang/test/Semantics/OpenMP/do-schedule02.f90 | 2 ++ flang/test/Semantics/OpenMP/do-schedule03.f90 | 2 ++ flang/test/Semantics/OpenMP/do-schedule04.f90 | 2 ++ .../Semantics/OpenMP/do01-positivecase.f90 | 2 ++ flang/test/Semantics/OpenMP/do01.f90 | 2 ++ flang/test/Semantics/OpenMP/do02.f90 | 21 ---------------- flang/test/Semantics/OpenMP/do03.f90 | 2 ++ .../Semantics/OpenMP/do04-positivecase.f90 | 2 ++ flang/test/Semantics/OpenMP/do04.f90 | 2 ++ .../Semantics/OpenMP/do05-positivecase.f90 | 2 ++ flang/test/Semantics/OpenMP/do05.f90 | 2 ++ .../Semantics/OpenMP/do06-positivecases.f90 | 2 ++ flang/test/Semantics/OpenMP/do06.f90 | 2 ++ flang/test/Semantics/OpenMP/do07.f90 | 2 ++ flang/test/Semantics/OpenMP/do08.f90 | 2 ++ flang/test/Semantics/OpenMP/do09.f90 | 2 ++ flang/test/Semantics/OpenMP/do10.f90 | 2 ++ flang/test/Semantics/OpenMP/do11.f90 | 2 ++ flang/test/Semantics/OpenMP/do12.f90 | 2 ++ flang/test/Semantics/OpenMP/do13.f90 | 2 ++ flang/test/Semantics/OpenMP/do14.f90 | 2 ++ flang/test/Semantics/OpenMP/do15.f90 | 2 ++ flang/test/Semantics/OpenMP/do16.f90 | 2 ++ flang/test/Semantics/OpenMP/do17.f90 | 2 ++ flang/test/Semantics/OpenMP/do18.f90 | 2 ++ flang/test/Semantics/OpenMP/do19.f90 | 2 ++ flang/test/Semantics/OpenMP/do20.f90 | 2 ++ .../test/Semantics/OpenMP/firstprivate01.f90 | 2 ++ .../test/Semantics/OpenMP/firstprivate02.f90 | 2 ++ flang/test/Semantics/OpenMP/flush01.f90 | 2 ++ flang/test/Semantics/OpenMP/flush02.f90 | 2 ++ flang/test/Semantics/OpenMP/if-clause.f90 | 2 ++ flang/test/Semantics/OpenMP/implicit-dsa.f90 | 2 ++ .../test/Semantics/OpenMP/invalid-branch.f90 | 2 ++ flang/test/Semantics/OpenMP/lastprivate01.f90 | 2 ++ flang/test/Semantics/OpenMP/lastprivate02.f90 | 2 ++ flang/test/Semantics/OpenMP/lastprivate03.f90 | 2 ++ flang/test/Semantics/OpenMP/linear-iter.f90 | 2 ++ .../Semantics/OpenMP/loop-association.f90 | 2 ++ flang/test/Semantics/OpenMP/loop-simd01.f90 | 2 ++ flang/test/Semantics/OpenMP/map-clause.f90 | 2 ++ .../OpenMP/modfile-threadprivate.f90 | 2 ++ .../test/Semantics/OpenMP/nested-barrier.f90 | 2 ++ flang/test/Semantics/OpenMP/nested-cancel.f90 | 2 ++ .../OpenMP/nested-cancellation-point.f90 | 2 ++ .../Semantics/OpenMP/nested-distribute.f90 | 2 ++ flang/test/Semantics/OpenMP/nested-master.f90 | 2 ++ flang/test/Semantics/OpenMP/nested-simd.f90 | 2 ++ flang/test/Semantics/OpenMP/nested-target.f90 | 2 ++ flang/test/Semantics/OpenMP/nested-teams.f90 | 2 ++ flang/test/Semantics/OpenMP/nested01.f90 | 2 ++ .../OpenMP/no-dowhile-in-parallel.f90 | 2 ++ flang/test/Semantics/OpenMP/nontemporal.f90 | 2 ++ .../OpenMP/omp-atomic-assignment-stmt.f90 | 2 ++ .../Semantics/OpenMP/omp-do-collapse1.f90 | 2 ++ .../test/Semantics/OpenMP/order-clause01.f90 | 2 ++ flang/test/Semantics/OpenMP/ordered-simd.f90 | 2 ++ flang/test/Semantics/OpenMP/ordered01.f90 | 2 ++ flang/test/Semantics/OpenMP/ordered02.f90 | 2 ++ flang/test/Semantics/OpenMP/ordered03.f90 | 2 ++ .../Semantics/OpenMP/parallel-critical-do.f90 | 2 ++ .../Semantics/OpenMP/parallel-private01.f90 | 2 ++ .../Semantics/OpenMP/parallel-private02.f90 | 2 ++ .../Semantics/OpenMP/parallel-private03.f90 | 2 ++ .../Semantics/OpenMP/parallel-private04.f90 | 2 ++ .../Semantics/OpenMP/parallel-sections-do.f90 | 2 ++ .../Semantics/OpenMP/parallel-sections01.f90 | 2 ++ .../Semantics/OpenMP/parallel-shared01.f90 | 2 ++ .../Semantics/OpenMP/parallel-shared02.f90 | 2 ++ .../Semantics/OpenMP/parallel-shared03.f90 | 2 ++ .../Semantics/OpenMP/parallel-shared04.f90 | 2 ++ flang/test/Semantics/OpenMP/parallel01.f90 | 2 ++ flang/test/Semantics/OpenMP/parallel02.f90 | 2 ++ .../private-is-pointer-allocatable-check.f90 | 2 ++ flang/test/Semantics/OpenMP/private01.f90 | 2 ++ flang/test/Semantics/OpenMP/private02.f90 | 2 ++ .../Semantics/OpenMP/reduction-subtract.f90 | 2 ++ flang/test/Semantics/OpenMP/reduction01.f90 | 2 ++ flang/test/Semantics/OpenMP/reduction02.f90 | 2 ++ flang/test/Semantics/OpenMP/reduction03.f90 | 2 ++ flang/test/Semantics/OpenMP/reduction04.f90 | 2 ++ flang/test/Semantics/OpenMP/reduction05.f90 | 2 ++ flang/test/Semantics/OpenMP/reduction06.f90 | 2 ++ flang/test/Semantics/OpenMP/reduction07.f90 | 2 ++ flang/test/Semantics/OpenMP/reduction08.f90 | 2 ++ flang/test/Semantics/OpenMP/reduction09.f90 | 2 ++ flang/test/Semantics/OpenMP/reduction10.f90 | 2 ++ flang/test/Semantics/OpenMP/reduction11.f90 | 2 ++ flang/test/Semantics/OpenMP/reduction12.f90 | 2 ++ .../Semantics/OpenMP/requires-atomic01.f90 | 2 ++ .../Semantics/OpenMP/requires-atomic02.f90 | 2 ++ flang/test/Semantics/OpenMP/requires01.f90 | 2 ++ flang/test/Semantics/OpenMP/requires02.f90 | 2 ++ flang/test/Semantics/OpenMP/requires03.f90 | 2 ++ flang/test/Semantics/OpenMP/requires04.f90 | 2 ++ flang/test/Semantics/OpenMP/requires05.f90 | 2 ++ flang/test/Semantics/OpenMP/requires06.f90 | 2 ++ flang/test/Semantics/OpenMP/requires07.f90 | 2 ++ flang/test/Semantics/OpenMP/requires08.f90 | 2 ++ flang/test/Semantics/OpenMP/requires09.f90 | 2 ++ flang/test/Semantics/OpenMP/resolve01.f90 | 2 ++ flang/test/Semantics/OpenMP/resolve02.f90 | 2 ++ flang/test/Semantics/OpenMP/resolve03.f90 | 2 ++ flang/test/Semantics/OpenMP/resolve04.f90 | 2 ++ flang/test/Semantics/OpenMP/resolve05.f90 | 2 ++ flang/test/Semantics/OpenMP/resolve06.f90 | 2 ++ flang/test/Semantics/OpenMP/sections01.f90 | 2 ++ flang/test/Semantics/OpenMP/sections02.f90 | 2 ++ flang/test/Semantics/OpenMP/sections03.f90 | 2 ++ flang/test/Semantics/OpenMP/simd-aligned.f90 | 2 ++ .../Semantics/OpenMP/simd-nontemporal.f90 | 2 ++ flang/test/Semantics/OpenMP/simd01.f90 | 2 ++ flang/test/Semantics/OpenMP/simd02.f90 | 2 ++ flang/test/Semantics/OpenMP/simd03.f90 | 2 ++ flang/test/Semantics/OpenMP/single01.f90 | 2 ++ flang/test/Semantics/OpenMP/single02.f90 | 2 ++ flang/test/Semantics/OpenMP/struct.f90 | 2 ++ flang/test/Semantics/OpenMP/symbol01.f90 | 2 ++ flang/test/Semantics/OpenMP/symbol02.f90 | 2 ++ flang/test/Semantics/OpenMP/symbol03.f90 | 2 ++ flang/test/Semantics/OpenMP/symbol04.f90 | 2 ++ flang/test/Semantics/OpenMP/symbol05.f90 | 2 ++ flang/test/Semantics/OpenMP/symbol06.f90 | 2 ++ flang/test/Semantics/OpenMP/symbol07.f90 | 2 ++ flang/test/Semantics/OpenMP/symbol08.f90 | 2 ++ flang/test/Semantics/OpenMP/symbol09.f90 | 2 ++ .../test/Semantics/OpenMP/sync-critical01.f90 | 2 ++ .../test/Semantics/OpenMP/sync-critical02.f90 | 2 ++ .../test/Semantics/OpenMP/target-update01.f90 | 2 ++ flang/test/Semantics/OpenMP/target.f90 | 2 ++ flang/test/Semantics/OpenMP/target01.f90 | 2 ++ flang/test/Semantics/OpenMP/target02.f90 | 2 ++ flang/test/Semantics/OpenMP/task01.f90 | 2 ++ flang/test/Semantics/OpenMP/taskgroup01.f90 | 4 ++- .../test/Semantics/OpenMP/taskloop-simd01.f90 | 2 ++ flang/test/Semantics/OpenMP/taskloop01.f90 | 2 ++ flang/test/Semantics/OpenMP/taskloop02.f90 | 2 ++ flang/test/Semantics/OpenMP/taskloop03.f90 | 25 ------------------- flang/test/Semantics/OpenMP/taskwait.f90 | 2 ++ .../test/Semantics/OpenMP/threadprivate01.f90 | 2 ++ .../test/Semantics/OpenMP/threadprivate02.f90 | 2 ++ .../test/Semantics/OpenMP/threadprivate03.f90 | 2 ++ .../test/Semantics/OpenMP/threadprivate04.f90 | 2 ++ .../test/Semantics/OpenMP/threadprivate05.f90 | 2 ++ .../test/Semantics/OpenMP/threadprivate06.f90 | 2 ++ .../test/Semantics/OpenMP/threadprivate07.f90 | 2 ++ .../test/Semantics/OpenMP/use_device_addr.f90 | 2 ++ .../Semantics/OpenMP/use_device_addr1.f90 | 2 ++ .../test/Semantics/OpenMP/use_device_ptr.f90 | 2 ++ .../test/Semantics/OpenMP/use_device_ptr1.f90 | 2 ++ flang/test/Semantics/OpenMP/workshare01.f90 | 2 ++ flang/test/Semantics/OpenMP/workshare02.f90 | 2 ++ flang/test/Semantics/OpenMP/workshare03.f90 | 2 ++ flang/test/Semantics/OpenMP/workshare04.f90 | 2 ++ flang/test/Semantics/OpenMP/workshare05.f90 | 2 ++ 220 files changed, 437 insertions(+), 47 deletions(-) delete mode 100644 flang/test/Semantics/OpenMP/do02.f90 delete mode 100644 flang/test/Semantics/OpenMP/taskloop03.f90 diff --git a/flang/test/Semantics/OpenMP/allocate-clause01.f90 b/flang/test/Semantics/OpenMP/allocate-clause01.f90 index 2b9a72e928eb..486166ec6338 100644 --- a/flang/test/Semantics/OpenMP/allocate-clause01.f90 +++ b/flang/test/Semantics/OpenMP/allocate-clause01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate-directive.f90 b/flang/test/Semantics/OpenMP/allocate-directive.f90 index 18a14b825f00..f55b724980fb 100644 --- a/flang/test/Semantics/OpenMP/allocate-directive.f90 +++ b/flang/test/Semantics/OpenMP/allocate-directive.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate01.f90 b/flang/test/Semantics/OpenMP/allocate01.f90 index 6ccb8bb09e83..a3d5fb5f90cd 100644 --- a/flang/test/Semantics/OpenMP/allocate01.f90 +++ b/flang/test/Semantics/OpenMP/allocate01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate02.f90 b/flang/test/Semantics/OpenMP/allocate02.f90 index 8f0579e810bb..b9bfdbe55aa2 100644 --- a/flang/test/Semantics/OpenMP/allocate02.f90 +++ b/flang/test/Semantics/OpenMP/allocate02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate03.f90 b/flang/test/Semantics/OpenMP/allocate03.f90 index e35115f3897c..ce577c857985 100644 --- a/flang/test/Semantics/OpenMP/allocate03.f90 +++ b/flang/test/Semantics/OpenMP/allocate03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate04.f90 b/flang/test/Semantics/OpenMP/allocate04.f90 index ea89d9446cc1..37f180cc16aa 100644 --- a/flang/test/Semantics/OpenMP/allocate04.f90 +++ b/flang/test/Semantics/OpenMP/allocate04.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate05.f90 b/flang/test/Semantics/OpenMP/allocate05.f90 index a787e8bb32a4..c4e0ace988bd 100644 --- a/flang/test/Semantics/OpenMP/allocate05.f90 +++ b/flang/test/Semantics/OpenMP/allocate05.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate06.f90 b/flang/test/Semantics/OpenMP/allocate06.f90 index e14134cd0730..e25b4c4decd5 100644 --- a/flang/test/Semantics/OpenMP/allocate06.f90 +++ b/flang/test/Semantics/OpenMP/allocate06.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate07.f90 b/flang/test/Semantics/OpenMP/allocate07.f90 index 396df598b252..2b0f17647b3c 100644 --- a/flang/test/Semantics/OpenMP/allocate07.f90 +++ b/flang/test/Semantics/OpenMP/allocate07.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate08.f90 b/flang/test/Semantics/OpenMP/allocate08.f90 index fc950ea4fca3..82aa11d69cfc 100644 --- a/flang/test/Semantics/OpenMP/allocate08.f90 +++ b/flang/test/Semantics/OpenMP/allocate08.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocate09.f90 b/flang/test/Semantics/OpenMP/allocate09.f90 index 0f93a340fe1e..3664c34c7e43 100644 --- a/flang/test/Semantics/OpenMP/allocate09.f90 +++ b/flang/test/Semantics/OpenMP/allocate09.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocators01.f90 b/flang/test/Semantics/OpenMP/allocators01.f90 index c75c522ecae1..f10db35f96d9 100644 --- a/flang/test/Semantics/OpenMP/allocators01.f90 +++ b/flang/test/Semantics/OpenMP/allocators01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocators02.f90 b/flang/test/Semantics/OpenMP/allocators02.f90 index 8055d21c6809..7f8fa3600277 100644 --- a/flang/test/Semantics/OpenMP/allocators02.f90 +++ b/flang/test/Semantics/OpenMP/allocators02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocators03.f90 b/flang/test/Semantics/OpenMP/allocators03.f90 index 03cff1b1e991..050cc2051c99 100644 --- a/flang/test/Semantics/OpenMP/allocators03.f90 +++ b/flang/test/Semantics/OpenMP/allocators03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocators04.f90 b/flang/test/Semantics/OpenMP/allocators04.f90 index 1d2e96443a9d..3c84030c4e39 100644 --- a/flang/test/Semantics/OpenMP/allocators04.f90 +++ b/flang/test/Semantics/OpenMP/allocators04.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocators05.f90 b/flang/test/Semantics/OpenMP/allocators05.f90 index d0e11ca5874d..8fd80b033756 100644 --- a/flang/test/Semantics/OpenMP/allocators05.f90 +++ b/flang/test/Semantics/OpenMP/allocators05.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/allocators06.f90 b/flang/test/Semantics/OpenMP/allocators06.f90 index a975204c1133..881182caa9b3 100644 --- a/flang/test/Semantics/OpenMP/allocators06.f90 +++ b/flang/test/Semantics/OpenMP/allocators06.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/atomic-hint-clause.f90 b/flang/test/Semantics/OpenMP/atomic-hint-clause.f90 index e157b7e1e73a..9050cbb0dca6 100644 --- a/flang/test/Semantics/OpenMP/atomic-hint-clause.f90 +++ b/flang/test/Semantics/OpenMP/atomic-hint-clause.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/atomic.f90 b/flang/test/Semantics/OpenMP/atomic.f90 index 44f06b7460bf..2f270ce33338 100644 --- a/flang/test/Semantics/OpenMP/atomic.f90 +++ b/flang/test/Semantics/OpenMP/atomic.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp use omp_lib ! Check OpenMP 2.13.6 atomic Construct diff --git a/flang/test/Semantics/OpenMP/atomic01.f90 b/flang/test/Semantics/OpenMP/atomic01.f90 index f0e1b47d2fa1..6ec94f3ff3a4 100644 --- a/flang/test/Semantics/OpenMP/atomic01.f90 +++ b/flang/test/Semantics/OpenMP/atomic01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/atomic02.f90 b/flang/test/Semantics/OpenMP/atomic02.f90 index b823bc4c33b2..92f2c4b9d040 100644 --- a/flang/test/Semantics/OpenMP/atomic02.f90 +++ b/flang/test/Semantics/OpenMP/atomic02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/atomic03.f90 b/flang/test/Semantics/OpenMP/atomic03.f90 index 76367495b986..4cce71dba351 100644 --- a/flang/test/Semantics/OpenMP/atomic03.f90 +++ b/flang/test/Semantics/OpenMP/atomic03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/atomic04.f90 b/flang/test/Semantics/OpenMP/atomic04.f90 index a9644ad95aa3..c03b230c837a 100644 --- a/flang/test/Semantics/OpenMP/atomic04.f90 +++ b/flang/test/Semantics/OpenMP/atomic04.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/atomic05.f90 b/flang/test/Semantics/OpenMP/atomic05.f90 index 2d9566463309..cfba33968213 100644 --- a/flang/test/Semantics/OpenMP/atomic05.f90 +++ b/flang/test/Semantics/OpenMP/atomic05.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang %openmp_flags diff --git a/flang/test/Semantics/OpenMP/barrier.f90 b/flang/test/Semantics/OpenMP/barrier.f90 index 1483fbd08f95..5fc3f7f3bd70 100644 --- a/flang/test/Semantics/OpenMP/barrier.f90 +++ b/flang/test/Semantics/OpenMP/barrier.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp !$omp barrier diff --git a/flang/test/Semantics/OpenMP/clause-validity01.f90 b/flang/test/Semantics/OpenMP/clause-validity01.f90 index 22ac57065ffe..779be00b9eba 100644 --- a/flang/test/Semantics/OpenMP/clause-validity01.f90 +++ b/flang/test/Semantics/OpenMP/clause-validity01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags %openmp_module_flag diff --git a/flang/test/Semantics/OpenMP/combined-constructs.f90 b/flang/test/Semantics/OpenMP/combined-constructs.f90 index 35ab6fcac58b..ba504d1b8e22 100644 --- a/flang/test/Semantics/OpenMP/combined-constructs.f90 +++ b/flang/test/Semantics/OpenMP/combined-constructs.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp program main diff --git a/flang/test/Semantics/OpenMP/common-block.f90 b/flang/test/Semantics/OpenMP/common-block.f90 index e1ddd120da85..4ddc5474a628 100644 --- a/flang/test/Semantics/OpenMP/common-block.f90 +++ b/flang/test/Semantics/OpenMP/common-block.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %flang_fc1 -fopenmp -fdebug-dump-symbols %s | FileCheck %s program main diff --git a/flang/test/Semantics/OpenMP/compiler-directive.f90 b/flang/test/Semantics/OpenMP/compiler-directive.f90 index 5d3e9bae27fd..07363ac5ac1e 100644 --- a/flang/test/Semantics/OpenMP/compiler-directive.f90 +++ b/flang/test/Semantics/OpenMP/compiler-directive.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! CompilerDirective with openmp tests diff --git a/flang/test/Semantics/OpenMP/copyin01.f90 b/flang/test/Semantics/OpenMP/copyin01.f90 index 0051b5d441f0..387a9fc7cf0b 100644 --- a/flang/test/Semantics/OpenMP/copyin01.f90 +++ b/flang/test/Semantics/OpenMP/copyin01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.4.1 copyin Clause diff --git a/flang/test/Semantics/OpenMP/copyin02.f90 b/flang/test/Semantics/OpenMP/copyin02.f90 index 09b876677ea3..92512890e3ed 100644 --- a/flang/test/Semantics/OpenMP/copyin02.f90 +++ b/flang/test/Semantics/OpenMP/copyin02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.4.1 copyin Clause diff --git a/flang/test/Semantics/OpenMP/copyin03.f90 b/flang/test/Semantics/OpenMP/copyin03.f90 index 7c3759aa2e11..5c0a2e873d81 100644 --- a/flang/test/Semantics/OpenMP/copyin03.f90 +++ b/flang/test/Semantics/OpenMP/copyin03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.4.1 copyin Clause diff --git a/flang/test/Semantics/OpenMP/copyin04.f90 b/flang/test/Semantics/OpenMP/copyin04.f90 index 6f5e8dfef217..7cbee5f4afab 100644 --- a/flang/test/Semantics/OpenMP/copyin04.f90 +++ b/flang/test/Semantics/OpenMP/copyin04.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.4.1 copyin Clause diff --git a/flang/test/Semantics/OpenMP/copyin05.f90 b/flang/test/Semantics/OpenMP/copyin05.f90 index 142d5a7345c6..aec6a7f88070 100644 --- a/flang/test/Semantics/OpenMP/copyin05.f90 +++ b/flang/test/Semantics/OpenMP/copyin05.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.4.1 copyin Clause diff --git a/flang/test/Semantics/OpenMP/copying.f90 b/flang/test/Semantics/OpenMP/copying.f90 index 63fb39a0f26e..d56d2b8932cf 100644 --- a/flang/test/Semantics/OpenMP/copying.f90 +++ b/flang/test/Semantics/OpenMP/copying.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp -Werror -pedantic ! OpenMP Version 5.0 ! 2.19.4.4 firstprivate Clause diff --git a/flang/test/Semantics/OpenMP/copyprivate01.f90 b/flang/test/Semantics/OpenMP/copyprivate01.f90 index d5cf27347607..4920d7abbe7c 100644 --- a/flang/test/Semantics/OpenMP/copyprivate01.f90 +++ b/flang/test/Semantics/OpenMP/copyprivate01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.4.2 copyprivate Clause diff --git a/flang/test/Semantics/OpenMP/copyprivate02.f90 b/flang/test/Semantics/OpenMP/copyprivate02.f90 index 35fd6dddd20c..2157cd4cb558 100644 --- a/flang/test/Semantics/OpenMP/copyprivate02.f90 +++ b/flang/test/Semantics/OpenMP/copyprivate02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.4.2 copyprivate Clause diff --git a/flang/test/Semantics/OpenMP/copyprivate03.f90 b/flang/test/Semantics/OpenMP/copyprivate03.f90 index 9d39fdb6b13c..f1433ced8aac 100644 --- a/flang/test/Semantics/OpenMP/copyprivate03.f90 +++ b/flang/test/Semantics/OpenMP/copyprivate03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.4.2 copyprivate Clause diff --git a/flang/test/Semantics/OpenMP/critical-empty.f90 b/flang/test/Semantics/OpenMP/critical-empty.f90 index 2001c8a14a7b..706f6d806f55 100644 --- a/flang/test/Semantics/OpenMP/critical-empty.f90 +++ b/flang/test/Semantics/OpenMP/critical-empty.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! Test that there are no errors for an empty critical construct diff --git a/flang/test/Semantics/OpenMP/critical-hint-clause.f90 b/flang/test/Semantics/OpenMP/critical-hint-clause.f90 index 419187fa3bbf..d737d671973c 100644 --- a/flang/test/Semantics/OpenMP/critical-hint-clause.f90 +++ b/flang/test/Semantics/OpenMP/critical-hint-clause.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/dealloc.f90 b/flang/test/Semantics/OpenMP/dealloc.f90 index b25fa62377f6..876f74f96bcc 100644 --- a/flang/test/Semantics/OpenMP/dealloc.f90 +++ b/flang/test/Semantics/OpenMP/dealloc.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! Test to check that no errors are present when allocate statements diff --git a/flang/test/Semantics/OpenMP/declarative-directive.f90 b/flang/test/Semantics/OpenMP/declarative-directive.f90 index 4d10dc2d1b12..15a41479fdfd 100644 --- a/flang/test/Semantics/OpenMP/declarative-directive.f90 +++ b/flang/test/Semantics/OpenMP/declarative-directive.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! Check OpenMP declarative directives diff --git a/flang/test/Semantics/OpenMP/declare-target-common-block.f90 b/flang/test/Semantics/OpenMP/declare-target-common-block.f90 index 33a093a03a22..9e123add228f 100644 --- a/flang/test/Semantics/OpenMP/declare-target-common-block.f90 +++ b/flang/test/Semantics/OpenMP/declare-target-common-block.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %flang_fc1 -fopenmp -fdebug-dump-symbols %s | FileCheck %s PROGRAM main diff --git a/flang/test/Semantics/OpenMP/declare-target01.f90 b/flang/test/Semantics/OpenMP/declare-target01.f90 index 2c50a9248280..511132f80d2b 100644 --- a/flang/test/Semantics/OpenMP/declare-target01.f90 +++ b/flang/test/Semantics/OpenMP/declare-target01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/declare-target02.f90 b/flang/test/Semantics/OpenMP/declare-target02.f90 index 8166e10d702b..af9e766dddb1 100644 --- a/flang/test/Semantics/OpenMP/declare-target02.f90 +++ b/flang/test/Semantics/OpenMP/declare-target02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/declare-target03.f90 b/flang/test/Semantics/OpenMP/declare-target03.f90 index bb1ed90e390f..14694b62149a 100644 --- a/flang/test/Semantics/OpenMP/declare-target03.f90 +++ b/flang/test/Semantics/OpenMP/declare-target03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -pedantic ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/declare-target04.f90 b/flang/test/Semantics/OpenMP/declare-target04.f90 index 24f8b4abecd1..90b681e35975 100644 --- a/flang/test/Semantics/OpenMP/declare-target04.f90 +++ b/flang/test/Semantics/OpenMP/declare-target04.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/declare-target05.f90 b/flang/test/Semantics/OpenMP/declare-target05.f90 index 2334a8506b7e..7154f760f0ad 100644 --- a/flang/test/Semantics/OpenMP/declare-target05.f90 +++ b/flang/test/Semantics/OpenMP/declare-target05.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/declare-target06.f90 b/flang/test/Semantics/OpenMP/declare-target06.f90 index a1c55d39e1b6..ffd7f038445e 100644 --- a/flang/test/Semantics/OpenMP/declare-target06.f90 +++ b/flang/test/Semantics/OpenMP/declare-target06.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/declare-target07.f90 b/flang/test/Semantics/OpenMP/declare-target07.f90 index 22b4a4bd081d..d901c9ccadff 100644 --- a/flang/test/Semantics/OpenMP/declare-target07.f90 +++ b/flang/test/Semantics/OpenMP/declare-target07.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp module my_module diff --git a/flang/test/Semantics/OpenMP/default-clause.f90 b/flang/test/Semantics/OpenMP/default-clause.f90 index 9cde77be2bab..eaea88115f48 100644 --- a/flang/test/Semantics/OpenMP/default-clause.f90 +++ b/flang/test/Semantics/OpenMP/default-clause.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %flang_fc1 -fopenmp -fdebug-dump-symbols %s | FileCheck %s ! Test symbols generated in block constructs in the diff --git a/flang/test/Semantics/OpenMP/default-none.f90 b/flang/test/Semantics/OpenMP/default-none.f90 index 11ba878ea779..44ddc9671299 100644 --- a/flang/test/Semantics/OpenMP/default-none.f90 +++ b/flang/test/Semantics/OpenMP/default-none.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows !RUN: %python %S/../test_errors.py %s %flang -fopenmp ! Positive tests for default(none) subroutine sb2(x) diff --git a/flang/test/Semantics/OpenMP/default.f90 b/flang/test/Semantics/OpenMP/default.f90 index 94de7fa46869..917eeaa0f4ac 100644 --- a/flang/test/Semantics/OpenMP/default.f90 +++ b/flang/test/Semantics/OpenMP/default.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows !RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.3.1 default Clause diff --git a/flang/test/Semantics/OpenMP/default02.f90 b/flang/test/Semantics/OpenMP/default02.f90 index 23f994bcc392..08200a412428 100644 --- a/flang/test/Semantics/OpenMP/default02.f90 +++ b/flang/test/Semantics/OpenMP/default02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows !RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.3.1 default Clause - a positive test case. diff --git a/flang/test/Semantics/OpenMP/depend01.f90 b/flang/test/Semantics/OpenMP/depend01.f90 index 29468f435885..870e3865a405 100644 --- a/flang/test/Semantics/OpenMP/depend01.f90 +++ b/flang/test/Semantics/OpenMP/depend01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.13.9 Depend Clause diff --git a/flang/test/Semantics/OpenMP/depend02.f90 b/flang/test/Semantics/OpenMP/depend02.f90 index 76c02c8f9cba..a3191e7ed12c 100644 --- a/flang/test/Semantics/OpenMP/depend02.f90 +++ b/flang/test/Semantics/OpenMP/depend02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.13.9 Depend Clause diff --git a/flang/test/Semantics/OpenMP/depend03.f90 b/flang/test/Semantics/OpenMP/depend03.f90 index e0eb683d252e..e7b88acd954f 100644 --- a/flang/test/Semantics/OpenMP/depend03.f90 +++ b/flang/test/Semantics/OpenMP/depend03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.13.9 Depend Clause diff --git a/flang/test/Semantics/OpenMP/device-clause01.f90 b/flang/test/Semantics/OpenMP/device-clause01.f90 index 6f95d162790d..88bc29e43bf6 100644 --- a/flang/test/Semantics/OpenMP/device-clause01.f90 +++ b/flang/test/Semantics/OpenMP/device-clause01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.2 ! 13.2 Device clause diff --git a/flang/test/Semantics/OpenMP/device-constructs.f90 b/flang/test/Semantics/OpenMP/device-constructs.f90 index 1ac00ef922c6..6018f8fa9dfb 100644 --- a/flang/test/Semantics/OpenMP/device-constructs.f90 +++ b/flang/test/Semantics/OpenMP/device-constructs.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! Check OpenMP clause validity for the following directives: ! 2.10 Device constructs diff --git a/flang/test/Semantics/OpenMP/do-collapse-positivecases.f90 b/flang/test/Semantics/OpenMP/do-collapse-positivecases.f90 index 6ad14fa01bca..2065b4eacdfd 100644 --- a/flang/test/Semantics/OpenMP/do-collapse-positivecases.f90 +++ b/flang/test/Semantics/OpenMP/do-collapse-positivecases.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows !RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Collapse Clause Positive cases diff --git a/flang/test/Semantics/OpenMP/do-collapse.f90 b/flang/test/Semantics/OpenMP/do-collapse.f90 index 145b7b75d28d..c8bbb39519f5 100644 --- a/flang/test/Semantics/OpenMP/do-collapse.f90 +++ b/flang/test/Semantics/OpenMP/do-collapse.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows !RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Collapse Clause diff --git a/flang/test/Semantics/OpenMP/do-cycle.f90 b/flang/test/Semantics/OpenMP/do-cycle.f90 index b6617acb0794..bdfd93b46e43 100644 --- a/flang/test/Semantics/OpenMP/do-cycle.f90 +++ b/flang/test/Semantics/OpenMP/do-cycle.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! Check for cycle statements leaving an OpenMP structured block diff --git a/flang/test/Semantics/OpenMP/do-ordered-positivecases.f90 b/flang/test/Semantics/OpenMP/do-ordered-positivecases.f90 index d4c4e5b1bf2f..02d91a85cbf2 100644 --- a/flang/test/Semantics/OpenMP/do-ordered-positivecases.f90 +++ b/flang/test/Semantics/OpenMP/do-ordered-positivecases.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows !RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Ordered Clause positive cases. diff --git a/flang/test/Semantics/OpenMP/do-ordered.f90 b/flang/test/Semantics/OpenMP/do-ordered.f90 index 79ded3e1b6fe..7bc4a92c68eb 100644 --- a/flang/test/Semantics/OpenMP/do-ordered.f90 +++ b/flang/test/Semantics/OpenMP/do-ordered.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows !RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Ordered Clause diff --git a/flang/test/Semantics/OpenMP/do-schedule01.f90 b/flang/test/Semantics/OpenMP/do-schedule01.f90 index 1e0a8a613135..3fc46ff77206 100644 --- a/flang/test/Semantics/OpenMP/do-schedule01.f90 +++ b/flang/test/Semantics/OpenMP/do-schedule01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Schedule Clause diff --git a/flang/test/Semantics/OpenMP/do-schedule02.f90 b/flang/test/Semantics/OpenMP/do-schedule02.f90 index a7cbdc24e83a..d08c69645ebb 100644 --- a/flang/test/Semantics/OpenMP/do-schedule02.f90 +++ b/flang/test/Semantics/OpenMP/do-schedule02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows !RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Schedule Clause diff --git a/flang/test/Semantics/OpenMP/do-schedule03.f90 b/flang/test/Semantics/OpenMP/do-schedule03.f90 index 8787b094d581..f7167e14b3f5 100644 --- a/flang/test/Semantics/OpenMP/do-schedule03.f90 +++ b/flang/test/Semantics/OpenMP/do-schedule03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Schedule Clause diff --git a/flang/test/Semantics/OpenMP/do-schedule04.f90 b/flang/test/Semantics/OpenMP/do-schedule04.f90 index 0d1e189593ea..fb816aab256d 100644 --- a/flang/test/Semantics/OpenMP/do-schedule04.f90 +++ b/flang/test/Semantics/OpenMP/do-schedule04.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Schedule Clause diff --git a/flang/test/Semantics/OpenMP/do01-positivecase.f90 b/flang/test/Semantics/OpenMP/do01-positivecase.f90 index 905fdbaf1847..c2b0894d7071 100644 --- a/flang/test/Semantics/OpenMP/do01-positivecase.f90 +++ b/flang/test/Semantics/OpenMP/do01-positivecase.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Loop Construct diff --git a/flang/test/Semantics/OpenMP/do01.f90 b/flang/test/Semantics/OpenMP/do01.f90 index 78c3ba38bc87..0cef5b710c09 100644 --- a/flang/test/Semantics/OpenMP/do01.f90 +++ b/flang/test/Semantics/OpenMP/do01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Loop Construct diff --git a/flang/test/Semantics/OpenMP/do02.f90 b/flang/test/Semantics/OpenMP/do02.f90 deleted file mode 100644 index 9749991e4f96..000000000000 --- a/flang/test/Semantics/OpenMP/do02.f90 +++ /dev/null @@ -1,21 +0,0 @@ -! RUN: %S/test_errors.sh %s %t %flang -fopenmp -! XFAIL: * - -! OpenMP Version 4.5 -! 2.7.1 Loop Construct -! Exit statement terminating !$OMP DO loop - -program omp_do - integer i, j, k - - !$omp do - do i = 1, 10 - do j = 1, 10 - print *, "Hello" - end do - !ERROR: EXIT statement terminating !$OMP DO loop - exit - end do - !$omp end do - -end program omp_do diff --git a/flang/test/Semantics/OpenMP/do03.f90 b/flang/test/Semantics/OpenMP/do03.f90 index 7ec84a0a3424..62733f89d528 100644 --- a/flang/test/Semantics/OpenMP/do03.f90 +++ b/flang/test/Semantics/OpenMP/do03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 diff --git a/flang/test/Semantics/OpenMP/do04-positivecase.f90 b/flang/test/Semantics/OpenMP/do04-positivecase.f90 index eb2d67bb8ceb..7de3908096ad 100644 --- a/flang/test/Semantics/OpenMP/do04-positivecase.f90 +++ b/flang/test/Semantics/OpenMP/do04-positivecase.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Do Loop Constructs diff --git a/flang/test/Semantics/OpenMP/do04.f90 b/flang/test/Semantics/OpenMP/do04.f90 index 6690f4927f6a..7e214ecc5a5c 100644 --- a/flang/test/Semantics/OpenMP/do04.f90 +++ b/flang/test/Semantics/OpenMP/do04.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Loop Construct diff --git a/flang/test/Semantics/OpenMP/do05-positivecase.f90 b/flang/test/Semantics/OpenMP/do05-positivecase.f90 index 4e02235f58a1..9daea23551ea 100644 --- a/flang/test/Semantics/OpenMP/do05-positivecase.f90 +++ b/flang/test/Semantics/OpenMP/do05-positivecase.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Loop Construct restrictions on single directive. diff --git a/flang/test/Semantics/OpenMP/do05.f90 b/flang/test/Semantics/OpenMP/do05.f90 index c0f240db57b6..73c656690715 100644 --- a/flang/test/Semantics/OpenMP/do05.f90 +++ b/flang/test/Semantics/OpenMP/do05.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Loop Construct restrictions on single directive. diff --git a/flang/test/Semantics/OpenMP/do06-positivecases.f90 b/flang/test/Semantics/OpenMP/do06-positivecases.f90 index 2713b55fa2ec..b66a7ef4ccc3 100644 --- a/flang/test/Semantics/OpenMP/do06-positivecases.f90 +++ b/flang/test/Semantics/OpenMP/do06-positivecases.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Loop Construct diff --git a/flang/test/Semantics/OpenMP/do06.f90 b/flang/test/Semantics/OpenMP/do06.f90 index 86790c2930e2..9efb50b7ca28 100644 --- a/flang/test/Semantics/OpenMP/do06.f90 +++ b/flang/test/Semantics/OpenMP/do06.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Loop Construct diff --git a/flang/test/Semantics/OpenMP/do07.f90 b/flang/test/Semantics/OpenMP/do07.f90 index 44fe5f86045a..2b371d7a939a 100644 --- a/flang/test/Semantics/OpenMP/do07.f90 +++ b/flang/test/Semantics/OpenMP/do07.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: not %flang -fsyntax-only -fopenmp %s 2>&1 | FileCheck %s ! REQUIRES: shell ! OpenMP Version 4.5 diff --git a/flang/test/Semantics/OpenMP/do08.f90 b/flang/test/Semantics/OpenMP/do08.f90 index 5143dff0dd31..5282b230ed72 100644 --- a/flang/test/Semantics/OpenMP/do08.f90 +++ b/flang/test/Semantics/OpenMP/do08.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Loop Construct diff --git a/flang/test/Semantics/OpenMP/do09.f90 b/flang/test/Semantics/OpenMP/do09.f90 index af9f2e294ace..e87d94cc20a1 100644 --- a/flang/test/Semantics/OpenMP/do09.f90 +++ b/flang/test/Semantics/OpenMP/do09.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Loop Construct diff --git a/flang/test/Semantics/OpenMP/do10.f90 b/flang/test/Semantics/OpenMP/do10.f90 index 7e8105e125a9..07c7161e6ab1 100644 --- a/flang/test/Semantics/OpenMP/do10.f90 +++ b/flang/test/Semantics/OpenMP/do10.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Loop Construct diff --git a/flang/test/Semantics/OpenMP/do11.f90 b/flang/test/Semantics/OpenMP/do11.f90 index faab457efff3..86b4e919e720 100644 --- a/flang/test/Semantics/OpenMP/do11.f90 +++ b/flang/test/Semantics/OpenMP/do11.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Do Loop Constructs diff --git a/flang/test/Semantics/OpenMP/do12.f90 b/flang/test/Semantics/OpenMP/do12.f90 index a057a246f7a9..e49304e86898 100644 --- a/flang/test/Semantics/OpenMP/do12.f90 +++ b/flang/test/Semantics/OpenMP/do12.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Do Loop constructs. diff --git a/flang/test/Semantics/OpenMP/do13.f90 b/flang/test/Semantics/OpenMP/do13.f90 index 6e9d1dddade4..9c9cdf42fe26 100644 --- a/flang/test/Semantics/OpenMP/do13.f90 +++ b/flang/test/Semantics/OpenMP/do13.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Loop Construct diff --git a/flang/test/Semantics/OpenMP/do14.f90 b/flang/test/Semantics/OpenMP/do14.f90 index 5e8a5a64c297..33fed997a47f 100644 --- a/flang/test/Semantics/OpenMP/do14.f90 +++ b/flang/test/Semantics/OpenMP/do14.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Do Loop constructs. diff --git a/flang/test/Semantics/OpenMP/do15.f90 b/flang/test/Semantics/OpenMP/do15.f90 index 45c591e66361..890a8dc7e416 100644 --- a/flang/test/Semantics/OpenMP/do15.f90 +++ b/flang/test/Semantics/OpenMP/do15.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Loop Construct diff --git a/flang/test/Semantics/OpenMP/do16.f90 b/flang/test/Semantics/OpenMP/do16.f90 index 15d13f683cf1..94cc69db7130 100644 --- a/flang/test/Semantics/OpenMP/do16.f90 +++ b/flang/test/Semantics/OpenMP/do16.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Loop Construct diff --git a/flang/test/Semantics/OpenMP/do17.f90 b/flang/test/Semantics/OpenMP/do17.f90 index c0c59f16dee1..a12a3dfb4d13 100644 --- a/flang/test/Semantics/OpenMP/do17.f90 +++ b/flang/test/Semantics/OpenMP/do17.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Do Loop constructs. diff --git a/flang/test/Semantics/OpenMP/do18.f90 b/flang/test/Semantics/OpenMP/do18.f90 index cdac323240ee..32ed756691af 100644 --- a/flang/test/Semantics/OpenMP/do18.f90 +++ b/flang/test/Semantics/OpenMP/do18.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %flang_fc1 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! RUN: %flang_fc1 -fopenmp -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK-NOT: do *[1-9] diff --git a/flang/test/Semantics/OpenMP/do19.f90 b/flang/test/Semantics/OpenMP/do19.f90 index 3dab59d615e5..e5bb6da7d08b 100644 --- a/flang/test/Semantics/OpenMP/do19.f90 +++ b/flang/test/Semantics/OpenMP/do19.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %flang_fc1 -fopenmp -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s ! CHECK-NOT: do *[1-9] ! CHECK: omp simd diff --git a/flang/test/Semantics/OpenMP/do20.f90 b/flang/test/Semantics/OpenMP/do20.f90 index 915d01e69edd..cabe07e0419c 100644 --- a/flang/test/Semantics/OpenMP/do20.f90 +++ b/flang/test/Semantics/OpenMP/do20.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! OpenMP 5.2 5.1.1 diff --git a/flang/test/Semantics/OpenMP/firstprivate01.f90 b/flang/test/Semantics/OpenMP/firstprivate01.f90 index 0c576a9f07a4..28521dab78c6 100644 --- a/flang/test/Semantics/OpenMP/firstprivate01.f90 +++ b/flang/test/Semantics/OpenMP/firstprivate01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.3.4 firstprivate Clause diff --git a/flang/test/Semantics/OpenMP/firstprivate02.f90 b/flang/test/Semantics/OpenMP/firstprivate02.f90 index eb2597cb1cc4..a27508a9a57c 100644 --- a/flang/test/Semantics/OpenMP/firstprivate02.f90 +++ b/flang/test/Semantics/OpenMP/firstprivate02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.2, Sections 3.2.1 & 5.3 subroutine omp_firstprivate(init) diff --git a/flang/test/Semantics/OpenMP/flush01.f90 b/flang/test/Semantics/OpenMP/flush01.f90 index 27324de4a8f7..0b5ce50e24eb 100644 --- a/flang/test/Semantics/OpenMP/flush01.f90 +++ b/flang/test/Semantics/OpenMP/flush01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! 2.17.8 Flush construct [OpenMP 5.0] diff --git a/flang/test/Semantics/OpenMP/flush02.f90 b/flang/test/Semantics/OpenMP/flush02.f90 index 18a0d0356bbd..6cb6b4b34a1b 100644 --- a/flang/test/Semantics/OpenMP/flush02.f90 +++ b/flang/test/Semantics/OpenMP/flush02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/if-clause.f90 b/flang/test/Semantics/OpenMP/if-clause.f90 index 493c6c873bfb..4a2e28e54f06 100644 --- a/flang/test/Semantics/OpenMP/if-clause.f90 +++ b/flang/test/Semantics/OpenMP/if-clause.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! Check OpenMP 'if' clause validity for all directives that can have it diff --git a/flang/test/Semantics/OpenMP/implicit-dsa.f90 b/flang/test/Semantics/OpenMP/implicit-dsa.f90 index 92d2421d06f9..590e0f270194 100644 --- a/flang/test/Semantics/OpenMP/implicit-dsa.f90 +++ b/flang/test/Semantics/OpenMP/implicit-dsa.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! Test symbols generated in block constructs that have implicitly diff --git a/flang/test/Semantics/OpenMP/invalid-branch.f90 b/flang/test/Semantics/OpenMP/invalid-branch.f90 index ed9e4d268f65..3f2eacec22bc 100644 --- a/flang/test/Semantics/OpenMP/invalid-branch.f90 +++ b/flang/test/Semantics/OpenMP/invalid-branch.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: not %flang -fsyntax-only -fopenmp %s 2>&1 | FileCheck %s ! REQUIRES: shell ! OpenMP Version 4.5 diff --git a/flang/test/Semantics/OpenMP/lastprivate01.f90 b/flang/test/Semantics/OpenMP/lastprivate01.f90 index 4fae4829d886..af207948f23a 100644 --- a/flang/test/Semantics/OpenMP/lastprivate01.f90 +++ b/flang/test/Semantics/OpenMP/lastprivate01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.3.5 lastprivate Clause diff --git a/flang/test/Semantics/OpenMP/lastprivate02.f90 b/flang/test/Semantics/OpenMP/lastprivate02.f90 index c5bf9d7f50d0..632b0a49250a 100644 --- a/flang/test/Semantics/OpenMP/lastprivate02.f90 +++ b/flang/test/Semantics/OpenMP/lastprivate02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.3.5 lastprivate Clause diff --git a/flang/test/Semantics/OpenMP/lastprivate03.f90 b/flang/test/Semantics/OpenMP/lastprivate03.f90 index d7fe0c162f27..512dd7dc7247 100644 --- a/flang/test/Semantics/OpenMP/lastprivate03.f90 +++ b/flang/test/Semantics/OpenMP/lastprivate03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.2, Sections 3.2.1 & 5.3 subroutine omp_lastprivate(init) diff --git a/flang/test/Semantics/OpenMP/linear-iter.f90 b/flang/test/Semantics/OpenMP/linear-iter.f90 index 8102c1a03cd3..9bd3f570965a 100644 --- a/flang/test/Semantics/OpenMP/linear-iter.f90 +++ b/flang/test/Semantics/OpenMP/linear-iter.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! Various checks with the ordered construct diff --git a/flang/test/Semantics/OpenMP/loop-association.f90 b/flang/test/Semantics/OpenMP/loop-association.f90 index d2167663c5dd..99eab75b0173 100644 --- a/flang/test/Semantics/OpenMP/loop-association.f90 +++ b/flang/test/Semantics/OpenMP/loop-association.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! Check the association between OpenMPLoopConstruct and DoConstruct diff --git a/flang/test/Semantics/OpenMP/loop-simd01.f90 b/flang/test/Semantics/OpenMP/loop-simd01.f90 index 18878645c0c6..0315c79ea530 100644 --- a/flang/test/Semantics/OpenMP/loop-simd01.f90 +++ b/flang/test/Semantics/OpenMP/loop-simd01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 diff --git a/flang/test/Semantics/OpenMP/map-clause.f90 b/flang/test/Semantics/OpenMP/map-clause.f90 index a7430c3edeb9..8d1e45aa55cf 100644 --- a/flang/test/Semantics/OpenMP/map-clause.f90 +++ b/flang/test/Semantics/OpenMP/map-clause.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! Check OpenMP MAP clause validity. Section 5.8.3 OpenMP 5.2. diff --git a/flang/test/Semantics/OpenMP/modfile-threadprivate.f90 b/flang/test/Semantics/OpenMP/modfile-threadprivate.f90 index 74147c0494a5..febcd58ccb36 100644 --- a/flang/test/Semantics/OpenMP/modfile-threadprivate.f90 +++ b/flang/test/Semantics/OpenMP/modfile-threadprivate.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_modfile.py %s %flang_fc1 -fopenmp ! Check correct modfile generation for OpenMP threadprivate directive. diff --git a/flang/test/Semantics/OpenMP/nested-barrier.f90 b/flang/test/Semantics/OpenMP/nested-barrier.f90 index cad31d798560..14877dbcdfa1 100644 --- a/flang/test/Semantics/OpenMP/nested-barrier.f90 +++ b/flang/test/Semantics/OpenMP/nested-barrier.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! Various checks with the nesting of BARRIER construct diff --git a/flang/test/Semantics/OpenMP/nested-cancel.f90 b/flang/test/Semantics/OpenMP/nested-cancel.f90 index afd94a591a06..6dc566d87b09 100644 --- a/flang/test/Semantics/OpenMP/nested-cancel.f90 +++ b/flang/test/Semantics/OpenMP/nested-cancel.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.0 diff --git a/flang/test/Semantics/OpenMP/nested-cancellation-point.f90 b/flang/test/Semantics/OpenMP/nested-cancellation-point.f90 index 5392a31b2331..d9bbb3200664 100644 --- a/flang/test/Semantics/OpenMP/nested-cancellation-point.f90 +++ b/flang/test/Semantics/OpenMP/nested-cancellation-point.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.0 diff --git a/flang/test/Semantics/OpenMP/nested-distribute.f90 b/flang/test/Semantics/OpenMP/nested-distribute.f90 index ba8c3bf04b33..8a268350e1ac 100644 --- a/flang/test/Semantics/OpenMP/nested-distribute.f90 +++ b/flang/test/Semantics/OpenMP/nested-distribute.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! Check OpenMP clause validity for the following directives: ! 2.10 Device constructs diff --git a/flang/test/Semantics/OpenMP/nested-master.f90 b/flang/test/Semantics/OpenMP/nested-master.f90 index ef7d2cef6f88..da6b3db8defb 100644 --- a/flang/test/Semantics/OpenMP/nested-master.f90 +++ b/flang/test/Semantics/OpenMP/nested-master.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! Various checks with the nesting of MASTER construct diff --git a/flang/test/Semantics/OpenMP/nested-simd.f90 b/flang/test/Semantics/OpenMP/nested-simd.f90 index 4149b6d97e9d..14e298f3843d 100644 --- a/flang/test/Semantics/OpenMP/nested-simd.f90 +++ b/flang/test/Semantics/OpenMP/nested-simd.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! Various checks with the nesting of SIMD construct diff --git a/flang/test/Semantics/OpenMP/nested-target.f90 b/flang/test/Semantics/OpenMP/nested-target.f90 index 2267f70715d3..3d015c6a0a5b 100644 --- a/flang/test/Semantics/OpenMP/nested-target.f90 +++ b/flang/test/Semantics/OpenMP/nested-target.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -Werror -pedantic ! OpenMP Version 5.0 diff --git a/flang/test/Semantics/OpenMP/nested-teams.f90 b/flang/test/Semantics/OpenMP/nested-teams.f90 index 80c59e07fbaa..df2b092aaaae 100644 --- a/flang/test/Semantics/OpenMP/nested-teams.f90 +++ b/flang/test/Semantics/OpenMP/nested-teams.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.0 diff --git a/flang/test/Semantics/OpenMP/nested01.f90 b/flang/test/Semantics/OpenMP/nested01.f90 index 49c964ab86aa..df53ecdba4f5 100644 --- a/flang/test/Semantics/OpenMP/nested01.f90 +++ b/flang/test/Semantics/OpenMP/nested01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! Check OpenMP 2.17 Nesting of Regions diff --git a/flang/test/Semantics/OpenMP/no-dowhile-in-parallel.f90 b/flang/test/Semantics/OpenMP/no-dowhile-in-parallel.f90 index fb864fd32ef0..9e5d703b380a 100644 --- a/flang/test/Semantics/OpenMP/no-dowhile-in-parallel.f90 +++ b/flang/test/Semantics/OpenMP/no-dowhile-in-parallel.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp subroutine bug48308(x,i) diff --git a/flang/test/Semantics/OpenMP/nontemporal.f90 b/flang/test/Semantics/OpenMP/nontemporal.f90 index 6d24849575ee..866996aeb353 100644 --- a/flang/test/Semantics/OpenMP/nontemporal.f90 +++ b/flang/test/Semantics/OpenMP/nontemporal.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! REQUIRES: shell ! Check OpenMP clause validity for NONTEMPORAL clause diff --git a/flang/test/Semantics/OpenMP/omp-atomic-assignment-stmt.f90 b/flang/test/Semantics/OpenMP/omp-atomic-assignment-stmt.f90 index a346056dee38..a5d4108e3ada 100644 --- a/flang/test/Semantics/OpenMP/omp-atomic-assignment-stmt.f90 +++ b/flang/test/Semantics/OpenMP/omp-atomic-assignment-stmt.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/omp-do-collapse1.f90 b/flang/test/Semantics/OpenMP/omp-do-collapse1.f90 index 81f87d8239e5..d3550d52f294 100644 --- a/flang/test/Semantics/OpenMP/omp-do-collapse1.f90 +++ b/flang/test/Semantics/OpenMP/omp-do-collapse1.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: not %flang_fc1 -fdebug-unparse-with-symbols -fopenmp %s 2>&1 | FileCheck %s ! OpenMP Version 4.5 ! 2.7.1 Loop Construct diff --git a/flang/test/Semantics/OpenMP/order-clause01.f90 b/flang/test/Semantics/OpenMP/order-clause01.f90 index 247791fac15b..8359aefc324d 100644 --- a/flang/test/Semantics/OpenMP/order-clause01.f90 +++ b/flang/test/Semantics/OpenMP/order-clause01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp subroutine omp_order() diff --git a/flang/test/Semantics/OpenMP/ordered-simd.f90 b/flang/test/Semantics/OpenMP/ordered-simd.f90 index c33ec745f2dd..3dd2c7232bca 100644 --- a/flang/test/Semantics/OpenMP/ordered-simd.f90 +++ b/flang/test/Semantics/OpenMP/ordered-simd.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! Various checks with the ordered construct diff --git a/flang/test/Semantics/OpenMP/ordered01.f90 b/flang/test/Semantics/OpenMP/ordered01.f90 index 9433120fab10..69d61f134740 100644 --- a/flang/test/Semantics/OpenMP/ordered01.f90 +++ b/flang/test/Semantics/OpenMP/ordered01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/ordered02.f90 b/flang/test/Semantics/OpenMP/ordered02.f90 index ed320c82a979..0ecc7ea141a3 100644 --- a/flang/test/Semantics/OpenMP/ordered02.f90 +++ b/flang/test/Semantics/OpenMP/ordered02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/ordered03.f90 b/flang/test/Semantics/OpenMP/ordered03.f90 index 8dd4d035212d..59e312f8cfc2 100644 --- a/flang/test/Semantics/OpenMP/ordered03.f90 +++ b/flang/test/Semantics/OpenMP/ordered03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/parallel-critical-do.f90 b/flang/test/Semantics/OpenMP/parallel-critical-do.f90 index 6e10b46dea9a..6a40f0872e8b 100644 --- a/flang/test/Semantics/OpenMP/parallel-critical-do.f90 +++ b/flang/test/Semantics/OpenMP/parallel-critical-do.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! Check that loop iteration variables are private and predetermined, even when diff --git a/flang/test/Semantics/OpenMP/parallel-private01.f90 b/flang/test/Semantics/OpenMP/parallel-private01.f90 index a3d332c95ed2..a460059732a5 100644 --- a/flang/test/Semantics/OpenMP/parallel-private01.f90 +++ b/flang/test/Semantics/OpenMP/parallel-private01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows !RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.3.3 parallel private Clause diff --git a/flang/test/Semantics/OpenMP/parallel-private02.f90 b/flang/test/Semantics/OpenMP/parallel-private02.f90 index 8cb72159d6ab..89e9ff1af5db 100644 --- a/flang/test/Semantics/OpenMP/parallel-private02.f90 +++ b/flang/test/Semantics/OpenMP/parallel-private02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows !RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.3.3 parallel private Clause diff --git a/flang/test/Semantics/OpenMP/parallel-private03.f90 b/flang/test/Semantics/OpenMP/parallel-private03.f90 index 24a096302e53..c832645042e0 100644 --- a/flang/test/Semantics/OpenMP/parallel-private03.f90 +++ b/flang/test/Semantics/OpenMP/parallel-private03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows !RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.3.3 parallel private Clause diff --git a/flang/test/Semantics/OpenMP/parallel-private04.f90 b/flang/test/Semantics/OpenMP/parallel-private04.f90 index 67a669c9882a..52a4f659d653 100644 --- a/flang/test/Semantics/OpenMP/parallel-private04.f90 +++ b/flang/test/Semantics/OpenMP/parallel-private04.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows !RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.3.3 parallel private Clause diff --git a/flang/test/Semantics/OpenMP/parallel-sections-do.f90 b/flang/test/Semantics/OpenMP/parallel-sections-do.f90 index 39102175299b..b8ca1096d06b 100644 --- a/flang/test/Semantics/OpenMP/parallel-sections-do.f90 +++ b/flang/test/Semantics/OpenMP/parallel-sections-do.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! Check that loop iteration variables are private and predetermined, even when diff --git a/flang/test/Semantics/OpenMP/parallel-sections01.f90 b/flang/test/Semantics/OpenMP/parallel-sections01.f90 index 6c5a053bf49c..8a07bf9380ec 100644 --- a/flang/test/Semantics/OpenMP/parallel-sections01.f90 +++ b/flang/test/Semantics/OpenMP/parallel-sections01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang %openmp_flags diff --git a/flang/test/Semantics/OpenMP/parallel-shared01.f90 b/flang/test/Semantics/OpenMP/parallel-shared01.f90 index 7abfe1f7b163..89584d6cc123 100644 --- a/flang/test/Semantics/OpenMP/parallel-shared01.f90 +++ b/flang/test/Semantics/OpenMP/parallel-shared01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows !RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.3.2 parallel shared Clause diff --git a/flang/test/Semantics/OpenMP/parallel-shared02.f90 b/flang/test/Semantics/OpenMP/parallel-shared02.f90 index f59f5236dfd9..d7c4d4b0fea1 100644 --- a/flang/test/Semantics/OpenMP/parallel-shared02.f90 +++ b/flang/test/Semantics/OpenMP/parallel-shared02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows !RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.3.2 parallel shared Clause diff --git a/flang/test/Semantics/OpenMP/parallel-shared03.f90 b/flang/test/Semantics/OpenMP/parallel-shared03.f90 index 3d9111c7aaf1..5283918756ac 100644 --- a/flang/test/Semantics/OpenMP/parallel-shared03.f90 +++ b/flang/test/Semantics/OpenMP/parallel-shared03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows !RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.3.2 parallel shared Clause diff --git a/flang/test/Semantics/OpenMP/parallel-shared04.f90 b/flang/test/Semantics/OpenMP/parallel-shared04.f90 index 06b7fcfa01d7..c1e998ee8b06 100644 --- a/flang/test/Semantics/OpenMP/parallel-shared04.f90 +++ b/flang/test/Semantics/OpenMP/parallel-shared04.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows !RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.3.2 parallel shared Clause diff --git a/flang/test/Semantics/OpenMP/parallel01.f90 b/flang/test/Semantics/OpenMP/parallel01.f90 index 6d5dd581a9f2..3e7a678844bd 100644 --- a/flang/test/Semantics/OpenMP/parallel01.f90 +++ b/flang/test/Semantics/OpenMP/parallel01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: not %flang -fsyntax-only -fopenmp %s 2>&1 | FileCheck %s ! OpenMP Version 4.5 ! 2.5 parallel construct. diff --git a/flang/test/Semantics/OpenMP/parallel02.f90 b/flang/test/Semantics/OpenMP/parallel02.f90 index eff0e7c70d1a..3587afaeb122 100644 --- a/flang/test/Semantics/OpenMP/parallel02.f90 +++ b/flang/test/Semantics/OpenMP/parallel02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: not %flang -fsyntax-only -fopenmp %s 2>&1 | FileCheck %s ! OpenMP Version 4.5 ! 2.5 parallel construct. diff --git a/flang/test/Semantics/OpenMP/private-is-pointer-allocatable-check.f90 b/flang/test/Semantics/OpenMP/private-is-pointer-allocatable-check.f90 index 7b3915d9a110..d6631b4f625a 100644 --- a/flang/test/Semantics/OpenMP/private-is-pointer-allocatable-check.f90 +++ b/flang/test/Semantics/OpenMP/private-is-pointer-allocatable-check.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %flang_fc1 -fopenmp -fsyntax-only %s subroutine s diff --git a/flang/test/Semantics/OpenMP/private01.f90 b/flang/test/Semantics/OpenMP/private01.f90 index 052823a9f78a..3597e2070597 100644 --- a/flang/test/Semantics/OpenMP/private01.f90 +++ b/flang/test/Semantics/OpenMP/private01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.3.3 private Clause diff --git a/flang/test/Semantics/OpenMP/private02.f90 b/flang/test/Semantics/OpenMP/private02.f90 index a81e31998eeb..a7bcb79e9872 100644 --- a/flang/test/Semantics/OpenMP/private02.f90 +++ b/flang/test/Semantics/OpenMP/private02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.15.3.3 private Clause diff --git a/flang/test/Semantics/OpenMP/reduction-subtract.f90 b/flang/test/Semantics/OpenMP/reduction-subtract.f90 index d4034743a14d..2601c767c597 100644 --- a/flang/test/Semantics/OpenMP/reduction-subtract.f90 +++ b/flang/test/Semantics/OpenMP/reduction-subtract.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.2 ! Minus operation is deprecated in reduction diff --git a/flang/test/Semantics/OpenMP/reduction01.f90 b/flang/test/Semantics/OpenMP/reduction01.f90 index 0e1a8a571c58..e33f7ece8e92 100644 --- a/flang/test/Semantics/OpenMP/reduction01.f90 +++ b/flang/test/Semantics/OpenMP/reduction01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.3.6 Reduction Clause diff --git a/flang/test/Semantics/OpenMP/reduction02.f90 b/flang/test/Semantics/OpenMP/reduction02.f90 index 4fd9fbe2d8a5..792a88f773b2 100644 --- a/flang/test/Semantics/OpenMP/reduction02.f90 +++ b/flang/test/Semantics/OpenMP/reduction02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.3.6 Reduction Clause diff --git a/flang/test/Semantics/OpenMP/reduction03.f90 b/flang/test/Semantics/OpenMP/reduction03.f90 index 1ddc2903fecc..a24349668db0 100644 --- a/flang/test/Semantics/OpenMP/reduction03.f90 +++ b/flang/test/Semantics/OpenMP/reduction03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.3.6 Reduction Clause diff --git a/flang/test/Semantics/OpenMP/reduction04.f90 b/flang/test/Semantics/OpenMP/reduction04.f90 index 319ed9f245ab..5c434e33a04e 100644 --- a/flang/test/Semantics/OpenMP/reduction04.f90 +++ b/flang/test/Semantics/OpenMP/reduction04.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.3.6 Reduction Clause diff --git a/flang/test/Semantics/OpenMP/reduction05.f90 b/flang/test/Semantics/OpenMP/reduction05.f90 index aa115ed7454b..f859f9f1fd46 100644 --- a/flang/test/Semantics/OpenMP/reduction05.f90 +++ b/flang/test/Semantics/OpenMP/reduction05.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.3.6 Reduction Clause diff --git a/flang/test/Semantics/OpenMP/reduction06.f90 b/flang/test/Semantics/OpenMP/reduction06.f90 index 58290c61cae8..5bcdce852a5d 100644 --- a/flang/test/Semantics/OpenMP/reduction06.f90 +++ b/flang/test/Semantics/OpenMP/reduction06.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.3.6 Reduction Clause diff --git a/flang/test/Semantics/OpenMP/reduction07.f90 b/flang/test/Semantics/OpenMP/reduction07.f90 index 98ed69a8d846..bf252fde72b3 100644 --- a/flang/test/Semantics/OpenMP/reduction07.f90 +++ b/flang/test/Semantics/OpenMP/reduction07.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.3.6 Reduction Clause diff --git a/flang/test/Semantics/OpenMP/reduction08.f90 b/flang/test/Semantics/OpenMP/reduction08.f90 index 99163327cdaf..b26fc533869c 100644 --- a/flang/test/Semantics/OpenMP/reduction08.f90 +++ b/flang/test/Semantics/OpenMP/reduction08.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.3.6 Reduction Clause Positive cases diff --git a/flang/test/Semantics/OpenMP/reduction09.f90 b/flang/test/Semantics/OpenMP/reduction09.f90 index 095b49ba0c40..c5d95349020f 100644 --- a/flang/test/Semantics/OpenMP/reduction09.f90 +++ b/flang/test/Semantics/OpenMP/reduction09.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.3.6 Reduction Clause Positive cases. diff --git a/flang/test/Semantics/OpenMP/reduction10.f90 b/flang/test/Semantics/OpenMP/reduction10.f90 index 0f94594408b8..394ee737d72f 100644 --- a/flang/test/Semantics/OpenMP/reduction10.f90 +++ b/flang/test/Semantics/OpenMP/reduction10.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.15.3.6 Reduction Clause diff --git a/flang/test/Semantics/OpenMP/reduction11.f90 b/flang/test/Semantics/OpenMP/reduction11.f90 index 3893fe70b407..95a356f87526 100644 --- a/flang/test/Semantics/OpenMP/reduction11.f90 +++ b/flang/test/Semantics/OpenMP/reduction11.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %flang_fc1 -fopenmp -fdebug-dump-symbols -o - %s 2>&1 | FileCheck %s ! Check intrinsic reduction symbols (in this case "max" are marked as INTRINSIC diff --git a/flang/test/Semantics/OpenMP/reduction12.f90 b/flang/test/Semantics/OpenMP/reduction12.f90 index f896ca4aa60b..bfd6e04fc485 100644 --- a/flang/test/Semantics/OpenMP/reduction12.f90 +++ b/flang/test/Semantics/OpenMP/reduction12.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP 5.2: Section 5.5.5 : A procedure pointer must not appear in a diff --git a/flang/test/Semantics/OpenMP/requires-atomic01.f90 b/flang/test/Semantics/OpenMP/requires-atomic01.f90 index b39c9cdcc0bb..a14491653eb3 100644 --- a/flang/test/Semantics/OpenMP/requires-atomic01.f90 +++ b/flang/test/Semantics/OpenMP/requires-atomic01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %flang_fc1 -fopenmp -fdebug-dump-parse-tree %s 2>&1 | FileCheck %s ! Ensure that requires atomic_default_mem_order is used to update atomic ! operations with no explicit memory order set. diff --git a/flang/test/Semantics/OpenMP/requires-atomic02.f90 b/flang/test/Semantics/OpenMP/requires-atomic02.f90 index 3af83970e792..5175e8faaf8d 100644 --- a/flang/test/Semantics/OpenMP/requires-atomic02.f90 +++ b/flang/test/Semantics/OpenMP/requires-atomic02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %flang_fc1 -fopenmp -fdebug-dump-parse-tree %s 2>&1 | FileCheck %s ! Ensure that requires atomic_default_mem_order is used to update atomic ! operations with no explicit memory order set. ACQ_REL clause tested here. diff --git a/flang/test/Semantics/OpenMP/requires01.f90 b/flang/test/Semantics/OpenMP/requires01.f90 index 007135749cc8..35989889af4e 100644 --- a/flang/test/Semantics/OpenMP/requires01.f90 +++ b/flang/test/Semantics/OpenMP/requires01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp !$omp requires reverse_offload unified_shared_memory diff --git a/flang/test/Semantics/OpenMP/requires02.f90 b/flang/test/Semantics/OpenMP/requires02.f90 index 974bcceb10c6..7d689fb27302 100644 --- a/flang/test/Semantics/OpenMP/requires02.f90 +++ b/flang/test/Semantics/OpenMP/requires02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.0 ! 2.4 Requires directive diff --git a/flang/test/Semantics/OpenMP/requires03.f90 b/flang/test/Semantics/OpenMP/requires03.f90 index 4a23a6a4105f..c8b09018c835 100644 --- a/flang/test/Semantics/OpenMP/requires03.f90 +++ b/flang/test/Semantics/OpenMP/requires03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.0 ! 2.4 Requires directive diff --git a/flang/test/Semantics/OpenMP/requires04.f90 b/flang/test/Semantics/OpenMP/requires04.f90 index bb4101c1cbd6..fd6da68b428d 100644 --- a/flang/test/Semantics/OpenMP/requires04.f90 +++ b/flang/test/Semantics/OpenMP/requires04.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.0 ! 2.4 Requires directive diff --git a/flang/test/Semantics/OpenMP/requires05.f90 b/flang/test/Semantics/OpenMP/requires05.f90 index dd27e3895e39..0b566807a283 100644 --- a/flang/test/Semantics/OpenMP/requires05.f90 +++ b/flang/test/Semantics/OpenMP/requires05.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.0 ! 2.4 Requires directive diff --git a/flang/test/Semantics/OpenMP/requires06.f90 b/flang/test/Semantics/OpenMP/requires06.f90 index ba9bbf31b6e0..551dd9d10382 100644 --- a/flang/test/Semantics/OpenMP/requires06.f90 +++ b/flang/test/Semantics/OpenMP/requires06.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.0 ! 2.4 Requires directive diff --git a/flang/test/Semantics/OpenMP/requires07.f90 b/flang/test/Semantics/OpenMP/requires07.f90 index 2a36b4def919..d6926c5fdb38 100644 --- a/flang/test/Semantics/OpenMP/requires07.f90 +++ b/flang/test/Semantics/OpenMP/requires07.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.0 ! 2.4 Requires directive diff --git a/flang/test/Semantics/OpenMP/requires08.f90 b/flang/test/Semantics/OpenMP/requires08.f90 index 5f3b084078cc..0ad7f53eaf51 100644 --- a/flang/test/Semantics/OpenMP/requires08.f90 +++ b/flang/test/Semantics/OpenMP/requires08.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.0 ! 2.4 Requires directive diff --git a/flang/test/Semantics/OpenMP/requires09.f90 b/flang/test/Semantics/OpenMP/requires09.f90 index 2fa5d950b9c2..d4d5d6168ae7 100644 --- a/flang/test/Semantics/OpenMP/requires09.f90 +++ b/flang/test/Semantics/OpenMP/requires09.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.0 ! 2.4 Requires directive diff --git a/flang/test/Semantics/OpenMP/resolve01.f90 b/flang/test/Semantics/OpenMP/resolve01.f90 index 79b67885b8b9..0af616178116 100644 --- a/flang/test/Semantics/OpenMP/resolve01.f90 +++ b/flang/test/Semantics/OpenMP/resolve01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! 2.4 An array section designates a subset of the elements in an array. Although diff --git a/flang/test/Semantics/OpenMP/resolve02.f90 b/flang/test/Semantics/OpenMP/resolve02.f90 index 7c3d6331c82a..cc54f623fa37 100644 --- a/flang/test/Semantics/OpenMP/resolve02.f90 +++ b/flang/test/Semantics/OpenMP/resolve02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! Test the effect to name resolution from illegal clause diff --git a/flang/test/Semantics/OpenMP/resolve03.f90 b/flang/test/Semantics/OpenMP/resolve03.f90 index ebc66ca12ebf..62bd4e4f919d 100644 --- a/flang/test/Semantics/OpenMP/resolve03.f90 +++ b/flang/test/Semantics/OpenMP/resolve03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! 2.15.3 Although variables in common blocks can be accessed by use association diff --git a/flang/test/Semantics/OpenMP/resolve04.f90 b/flang/test/Semantics/OpenMP/resolve04.f90 index 7c61950c57f6..6efceed8302e 100644 --- a/flang/test/Semantics/OpenMP/resolve04.f90 +++ b/flang/test/Semantics/OpenMP/resolve04.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! 2.15.3 Data-Sharing Attribute Clauses diff --git a/flang/test/Semantics/OpenMP/resolve05.f90 b/flang/test/Semantics/OpenMP/resolve05.f90 index c4cebb48ac5c..5ec4b58f4b8f 100644 --- a/flang/test/Semantics/OpenMP/resolve05.f90 +++ b/flang/test/Semantics/OpenMP/resolve05.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! 2.15.3 Data-Sharing Attribute Clauses diff --git a/flang/test/Semantics/OpenMP/resolve06.f90 b/flang/test/Semantics/OpenMP/resolve06.f90 index 358b1b1cc282..4fce44288dc6 100644 --- a/flang/test/Semantics/OpenMP/resolve06.f90 +++ b/flang/test/Semantics/OpenMP/resolve06.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/sections01.f90 b/flang/test/Semantics/OpenMP/sections01.f90 index c26cc88dcc7a..00b5a6d8fbc4 100644 --- a/flang/test/Semantics/OpenMP/sections01.f90 +++ b/flang/test/Semantics/OpenMP/sections01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 diff --git a/flang/test/Semantics/OpenMP/sections02.f90 b/flang/test/Semantics/OpenMP/sections02.f90 index ee29922a72c0..912e7bc2a8ff 100644 --- a/flang/test/Semantics/OpenMP/sections02.f90 +++ b/flang/test/Semantics/OpenMP/sections02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang %openmp_flags diff --git a/flang/test/Semantics/OpenMP/sections03.f90 b/flang/test/Semantics/OpenMP/sections03.f90 index 69775013ea82..b170f8674d19 100644 --- a/flang/test/Semantics/OpenMP/sections03.f90 +++ b/flang/test/Semantics/OpenMP/sections03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp !XFAIL: * ! OpenMP version 5.0.0 diff --git a/flang/test/Semantics/OpenMP/simd-aligned.f90 b/flang/test/Semantics/OpenMP/simd-aligned.f90 index 0a9f95833e22..3ffdc68693fd 100644 --- a/flang/test/Semantics/OpenMP/simd-aligned.f90 +++ b/flang/test/Semantics/OpenMP/simd-aligned.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 diff --git a/flang/test/Semantics/OpenMP/simd-nontemporal.f90 b/flang/test/Semantics/OpenMP/simd-nontemporal.f90 index a488edd98cdc..074b0a2039ed 100644 --- a/flang/test/Semantics/OpenMP/simd-nontemporal.f90 +++ b/flang/test/Semantics/OpenMP/simd-nontemporal.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 diff --git a/flang/test/Semantics/OpenMP/simd01.f90 b/flang/test/Semantics/OpenMP/simd01.f90 index 1aa2880cda83..1e241648f75a 100644 --- a/flang/test/Semantics/OpenMP/simd01.f90 +++ b/flang/test/Semantics/OpenMP/simd01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.0 ! 2.9.3.1 simd Construct diff --git a/flang/test/Semantics/OpenMP/simd02.f90 b/flang/test/Semantics/OpenMP/simd02.f90 index a627e2ac2d67..24d6abd9761f 100644 --- a/flang/test/Semantics/OpenMP/simd02.f90 +++ b/flang/test/Semantics/OpenMP/simd02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 diff --git a/flang/test/Semantics/OpenMP/simd03.f90 b/flang/test/Semantics/OpenMP/simd03.f90 index 38f45da47748..8df48368fa96 100644 --- a/flang/test/Semantics/OpenMP/simd03.f90 +++ b/flang/test/Semantics/OpenMP/simd03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %S/test_errors.sh %s %t %flang -fopenmp ! XFAIL: * diff --git a/flang/test/Semantics/OpenMP/single01.f90 b/flang/test/Semantics/OpenMP/single01.f90 index 2e40bec56e9c..0468e695d8cf 100644 --- a/flang/test/Semantics/OpenMP/single01.f90 +++ b/flang/test/Semantics/OpenMP/single01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.3 single Construct diff --git a/flang/test/Semantics/OpenMP/single02.f90 b/flang/test/Semantics/OpenMP/single02.f90 index 03cf7fbb6ad3..9d9d306c2f53 100644 --- a/flang/test/Semantics/OpenMP/single02.f90 +++ b/flang/test/Semantics/OpenMP/single02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 ! 2.7.3 single Construct diff --git a/flang/test/Semantics/OpenMP/struct.f90 b/flang/test/Semantics/OpenMP/struct.f90 index 8ae1fbe4da86..3d2000aef993 100644 --- a/flang/test/Semantics/OpenMP/struct.f90 +++ b/flang/test/Semantics/OpenMP/struct.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! Check OpenMP compatibility with the DEC STRUCTURE extension diff --git a/flang/test/Semantics/OpenMP/symbol01.f90 b/flang/test/Semantics/OpenMP/symbol01.f90 index 0b435a9ab985..e2a9c01e9d5f 100644 --- a/flang/test/Semantics/OpenMP/symbol01.f90 +++ b/flang/test/Semantics/OpenMP/symbol01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! Test clauses that accept list. diff --git a/flang/test/Semantics/OpenMP/symbol02.f90 b/flang/test/Semantics/OpenMP/symbol02.f90 index f6ffc5500d0a..1b1dc4489448 100644 --- a/flang/test/Semantics/OpenMP/symbol02.f90 +++ b/flang/test/Semantics/OpenMP/symbol02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! 1.4.1 Structure of the OpenMP Memory Model diff --git a/flang/test/Semantics/OpenMP/symbol03.f90 b/flang/test/Semantics/OpenMP/symbol03.f90 index 93e9b7a3eae6..76d93577d3ac 100644 --- a/flang/test/Semantics/OpenMP/symbol03.f90 +++ b/flang/test/Semantics/OpenMP/symbol03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! 1.4.1 Structure of the OpenMP Memory Model diff --git a/flang/test/Semantics/OpenMP/symbol04.f90 b/flang/test/Semantics/OpenMP/symbol04.f90 index 808d1e0dd09b..8ef154ebbf9d 100644 --- a/flang/test/Semantics/OpenMP/symbol04.f90 +++ b/flang/test/Semantics/OpenMP/symbol04.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! 2.15.3 Data-Sharing Attribute Clauses diff --git a/flang/test/Semantics/OpenMP/symbol05.f90 b/flang/test/Semantics/OpenMP/symbol05.f90 index fa0a8f65a429..d08d85270380 100644 --- a/flang/test/Semantics/OpenMP/symbol05.f90 +++ b/flang/test/Semantics/OpenMP/symbol05.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! 2.15.2 threadprivate Directive diff --git a/flang/test/Semantics/OpenMP/symbol06.f90 b/flang/test/Semantics/OpenMP/symbol06.f90 index 906264eb1264..a2cd288dfd15 100644 --- a/flang/test/Semantics/OpenMP/symbol06.f90 +++ b/flang/test/Semantics/OpenMP/symbol06.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! 2.15.3 Data-Sharing Attribute Clauses diff --git a/flang/test/Semantics/OpenMP/symbol07.f90 b/flang/test/Semantics/OpenMP/symbol07.f90 index e2250f5c7908..ee6cd2a0df2e 100644 --- a/flang/test/Semantics/OpenMP/symbol07.f90 +++ b/flang/test/Semantics/OpenMP/symbol07.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! Generic tests diff --git a/flang/test/Semantics/OpenMP/symbol08.f90 b/flang/test/Semantics/OpenMP/symbol08.f90 index 3af85af74ee9..76db86cd54ca 100644 --- a/flang/test/Semantics/OpenMP/symbol08.f90 +++ b/flang/test/Semantics/OpenMP/symbol08.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! 2.15.1.1 Predetermined rules for associated do-loops index variable diff --git a/flang/test/Semantics/OpenMP/symbol09.f90 b/flang/test/Semantics/OpenMP/symbol09.f90 index e2250f5c7908..ee6cd2a0df2e 100644 --- a/flang/test/Semantics/OpenMP/symbol09.f90 +++ b/flang/test/Semantics/OpenMP/symbol09.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp ! Generic tests diff --git a/flang/test/Semantics/OpenMP/sync-critical01.f90 b/flang/test/Semantics/OpenMP/sync-critical01.f90 index b597eb17ea22..ef377ebc72f2 100644 --- a/flang/test/Semantics/OpenMP/sync-critical01.f90 +++ b/flang/test/Semantics/OpenMP/sync-critical01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.0 diff --git a/flang/test/Semantics/OpenMP/sync-critical02.f90 b/flang/test/Semantics/OpenMP/sync-critical02.f90 index 1fa9d6ad84f2..681aa7944c4f 100644 --- a/flang/test/Semantics/OpenMP/sync-critical02.f90 +++ b/flang/test/Semantics/OpenMP/sync-critical02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang %openmp_flags diff --git a/flang/test/Semantics/OpenMP/target-update01.f90 b/flang/test/Semantics/OpenMP/target-update01.f90 index 84dc60dcd75f..706d0ba8bafb 100644 --- a/flang/test/Semantics/OpenMP/target-update01.f90 +++ b/flang/test/Semantics/OpenMP/target-update01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp subroutine foo(x) diff --git a/flang/test/Semantics/OpenMP/target.f90 b/flang/test/Semantics/OpenMP/target.f90 index 994c04048edf..b98d27192ac9 100644 --- a/flang/test/Semantics/OpenMP/target.f90 +++ b/flang/test/Semantics/OpenMP/target.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -Werror ! Corner cases in OpenMP target directives diff --git a/flang/test/Semantics/OpenMP/target01.f90 b/flang/test/Semantics/OpenMP/target01.f90 index 9836f0112738..2da7ab5c9b10 100644 --- a/flang/test/Semantics/OpenMP/target01.f90 +++ b/flang/test/Semantics/OpenMP/target01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp subroutine foo(b) diff --git a/flang/test/Semantics/OpenMP/target02.f90 b/flang/test/Semantics/OpenMP/target02.f90 index 06ce1c0875cc..82b8ca1a430e 100644 --- a/flang/test/Semantics/OpenMP/target02.f90 +++ b/flang/test/Semantics/OpenMP/target02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 4.5 diff --git a/flang/test/Semantics/OpenMP/task01.f90 b/flang/test/Semantics/OpenMP/task01.f90 index 4dc80d6d70e0..de4321ebc578 100644 --- a/flang/test/Semantics/OpenMP/task01.f90 +++ b/flang/test/Semantics/OpenMP/task01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: not %flang -fsyntax-only -fopenmp %s 2>&1 | FileCheck %s ! OpenMP Version 4.5 ! 2.9.1 task Construct diff --git a/flang/test/Semantics/OpenMP/taskgroup01.f90 b/flang/test/Semantics/OpenMP/taskgroup01.f90 index 9de1df91bf3b..bdb5b985d5d3 100644 --- a/flang/test/Semantics/OpenMP/taskgroup01.f90 +++ b/flang/test/Semantics/OpenMP/taskgroup01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang %openmp_flags @@ -47,4 +49,4 @@ use omp_lib !$omp end taskgroup !$omp end task !$omp end parallel -end program \ No newline at end of file +end program diff --git a/flang/test/Semantics/OpenMP/taskloop-simd01.f90 b/flang/test/Semantics/OpenMP/taskloop-simd01.f90 index bb7266a52f61..6316b9629cf3 100644 --- a/flang/test/Semantics/OpenMP/taskloop-simd01.f90 +++ b/flang/test/Semantics/OpenMP/taskloop-simd01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.0 diff --git a/flang/test/Semantics/OpenMP/taskloop01.f90 b/flang/test/Semantics/OpenMP/taskloop01.f90 index 6bef58438151..2c5375949404 100644 --- a/flang/test/Semantics/OpenMP/taskloop01.f90 +++ b/flang/test/Semantics/OpenMP/taskloop01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.9.2 taskloop Construct diff --git a/flang/test/Semantics/OpenMP/taskloop02.f90 b/flang/test/Semantics/OpenMP/taskloop02.f90 index 867ef8a9806d..275b079d38a1 100644 --- a/flang/test/Semantics/OpenMP/taskloop02.f90 +++ b/flang/test/Semantics/OpenMP/taskloop02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: not %flang -fsyntax-only -fopenmp %s 2>&1 | FileCheck %s ! OpenMP Version 4.5 ! 2.9.2 taskloop Construct diff --git a/flang/test/Semantics/OpenMP/taskloop03.f90 b/flang/test/Semantics/OpenMP/taskloop03.f90 deleted file mode 100644 index 7e2e426a3fe7..000000000000 --- a/flang/test/Semantics/OpenMP/taskloop03.f90 +++ /dev/null @@ -1,25 +0,0 @@ -! RUN: %S/test_errors.sh %s %t %flang -fopenmp -! XFAIL: * - -! OpenMP Version 4.5 -! 2.9.2 taskloop Construct -! All loops associated with the taskloop construct must be perfectly nested, -! there must be no intervening code or any OpenMP directive between -! any two loops - -program omp_taskloop - integer i, j - - !$omp taskloop private(j) grainsize(500) nogroup - do i=1, 10000 - do j=1, i - call loop_body(i, j) - end do - !ERROR: Loops associated with !$omp taskloop is not perfectly nested - !$omp single - print *, "omp single" - !$omp end single - end do - !$omp end taskloop - -end program omp_taskloop diff --git a/flang/test/Semantics/OpenMP/taskwait.f90 b/flang/test/Semantics/OpenMP/taskwait.f90 index e60051c9da8a..a3b15c7a1df0 100644 --- a/flang/test/Semantics/OpenMP/taskwait.f90 +++ b/flang/test/Semantics/OpenMP/taskwait.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp !$omp taskwait diff --git a/flang/test/Semantics/OpenMP/threadprivate01.f90 b/flang/test/Semantics/OpenMP/threadprivate01.f90 index c2cf9ba99ab0..6597941ac3d5 100644 --- a/flang/test/Semantics/OpenMP/threadprivate01.f90 +++ b/flang/test/Semantics/OpenMP/threadprivate01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! REQUIRES: openmp_runtime ! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags diff --git a/flang/test/Semantics/OpenMP/threadprivate02.f90 b/flang/test/Semantics/OpenMP/threadprivate02.f90 index 7f6e8dcc8e8a..862d1e8a45c4 100644 --- a/flang/test/Semantics/OpenMP/threadprivate02.f90 +++ b/flang/test/Semantics/OpenMP/threadprivate02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/threadprivate03.f90 b/flang/test/Semantics/OpenMP/threadprivate03.f90 index b466a8e05e9c..57d3b9209820 100644 --- a/flang/test/Semantics/OpenMP/threadprivate03.f90 +++ b/flang/test/Semantics/OpenMP/threadprivate03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -pedantic ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/threadprivate04.f90 b/flang/test/Semantics/OpenMP/threadprivate04.f90 index 3d8c7fb8de8f..8199dbaea166 100644 --- a/flang/test/Semantics/OpenMP/threadprivate04.f90 +++ b/flang/test/Semantics/OpenMP/threadprivate04.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/threadprivate05.f90 b/flang/test/Semantics/OpenMP/threadprivate05.f90 index cdbf3701b70a..eecf9e781cf7 100644 --- a/flang/test/Semantics/OpenMP/threadprivate05.f90 +++ b/flang/test/Semantics/OpenMP/threadprivate05.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/threadprivate06.f90 b/flang/test/Semantics/OpenMP/threadprivate06.f90 index f31c38f6f2b2..5537a8805e9f 100644 --- a/flang/test/Semantics/OpenMP/threadprivate06.f90 +++ b/flang/test/Semantics/OpenMP/threadprivate06.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/threadprivate07.f90 b/flang/test/Semantics/OpenMP/threadprivate07.f90 index c9a006ca0e08..5302fdf4ab71 100644 --- a/flang/test/Semantics/OpenMP/threadprivate07.f90 +++ b/flang/test/Semantics/OpenMP/threadprivate07.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! Check Threadprivate Directive with local variable of a BLOCK construct. diff --git a/flang/test/Semantics/OpenMP/use_device_addr.f90 b/flang/test/Semantics/OpenMP/use_device_addr.f90 index 93a7643b5eb4..dda00d510504 100644 --- a/flang/test/Semantics/OpenMP/use_device_addr.f90 +++ b/flang/test/Semantics/OpenMP/use_device_addr.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %flang_fc1 -fopenmp -fdebug-dump-symbols %s | FileCheck %s ! OpenMP Version 5.1 ! 2.14.2 use_device_addr clause diff --git a/flang/test/Semantics/OpenMP/use_device_addr1.f90 b/flang/test/Semantics/OpenMP/use_device_addr1.f90 index 867e324b68ad..c37e9a3a7e3e 100644 --- a/flang/test/Semantics/OpenMP/use_device_addr1.f90 +++ b/flang/test/Semantics/OpenMP/use_device_addr1.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.0 ! 2.10.1 use_device_ptr clause diff --git a/flang/test/Semantics/OpenMP/use_device_ptr.f90 b/flang/test/Semantics/OpenMP/use_device_ptr.f90 index 64b98cf67961..e9e7fbb6c1f5 100644 --- a/flang/test/Semantics/OpenMP/use_device_ptr.f90 +++ b/flang/test/Semantics/OpenMP/use_device_ptr.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %flang_fc1 -fopenmp -fdebug-dump-symbols %s | FileCheck %s ! OpenMP Version 5.0 ! 2.10.1 use_device_ptr clause diff --git a/flang/test/Semantics/OpenMP/use_device_ptr1.f90 b/flang/test/Semantics/OpenMP/use_device_ptr1.f90 index 176fb5f35a84..f705c50370da 100644 --- a/flang/test/Semantics/OpenMP/use_device_ptr1.f90 +++ b/flang/test/Semantics/OpenMP/use_device_ptr1.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.0 ! 2.10.1 use_device_ptr clause diff --git a/flang/test/Semantics/OpenMP/workshare01.f90 b/flang/test/Semantics/OpenMP/workshare01.f90 index 9667a306061c..615c3408dc7a 100644 --- a/flang/test/Semantics/OpenMP/workshare01.f90 +++ b/flang/test/Semantics/OpenMP/workshare01.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.7.4 workshare Construct diff --git a/flang/test/Semantics/OpenMP/workshare02.f90 b/flang/test/Semantics/OpenMP/workshare02.f90 index e099ecb9f1e6..b6faf197f1f2 100644 --- a/flang/test/Semantics/OpenMP/workshare02.f90 +++ b/flang/test/Semantics/OpenMP/workshare02.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.7.4 workshare Construct diff --git a/flang/test/Semantics/OpenMP/workshare03.f90 b/flang/test/Semantics/OpenMP/workshare03.f90 index 09d46abf42ee..2aea0ccce3c7 100644 --- a/flang/test/Semantics/OpenMP/workshare03.f90 +++ b/flang/test/Semantics/OpenMP/workshare03.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.7.4 workshare Construct diff --git a/flang/test/Semantics/OpenMP/workshare04.f90 b/flang/test/Semantics/OpenMP/workshare04.f90 index 0ec635e52d2b..e84459978e15 100644 --- a/flang/test/Semantics/OpenMP/workshare04.f90 +++ b/flang/test/Semantics/OpenMP/workshare04.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.7.4 workshare Construct diff --git a/flang/test/Semantics/OpenMP/workshare05.f90 b/flang/test/Semantics/OpenMP/workshare05.f90 index b57053e092e6..30f3b988de91 100644 --- a/flang/test/Semantics/OpenMP/workshare05.f90 +++ b/flang/test/Semantics/OpenMP/workshare05.f90 @@ -1,3 +1,5 @@ +! UNSUPPORTED: system-windows +! Marking as unsupported due to suspected long runtime on Windows ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 4.5 ! 2.7.4 workshare Construct -- GitLab From e75b58cfc666fc168d05580d2b7fd274830a4dd0 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 20 May 2024 14:50:58 -0400 Subject: [PATCH 119/793] [Clang][Sema] Do not add implicit 'const' when matching constexpr function template explicit specializations after C++14 (#92449) Clang incorrectly accepts the following when using C++14 or later: ``` struct A { template void f() const; template<> constexpr void f(); }; ``` Non-static member functions declared `constexpr` are only implicitly `const` in C++11. This patch makes clang reject the explicit specialization of `f` in language modes after C++11. --- clang/docs/ReleaseNotes.rst | 2 + clang/lib/Sema/SemaTemplate.cpp | 15 ++-- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 13 +++- .../CXX/temp/temp.spec/temp.expl.spec/p12.cpp | 70 +++++++++++++++++++ 4 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 88616b5bee73..81e9d0423f96 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -747,6 +747,8 @@ Bug Fixes to C++ Support - Clang no longer transforms dependent qualified names into implicit class member access expressions until it can be determined whether the name is that of a non-static member. - Clang now correctly diagnoses when the current instantiation is used as an incomplete base class. +- Clang no longer treats ``constexpr`` class scope function template specializations of non-static members + as implicitly ``const`` in language modes after C++11. Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index de884260790c..02d9b64c2b14 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -10255,15 +10255,20 @@ bool Sema::CheckFunctionTemplateSpecialization( Ovl->getDeclContext()->getRedeclContext())) continue; + QualType FT = FD->getType(); + // C++11 [dcl.constexpr]p8: + // A constexpr specifier for a non-static member function that is not + // a constructor declares that member function to be const. + // // When matching a constexpr member function template specialization // against the primary template, we don't yet know whether the // specialization has an implicit 'const' (because we don't know whether // it will be a static member function until we know which template it - // specializes), so adjust it now assuming it specializes this template. - QualType FT = FD->getType(); - if (FD->isConstexpr()) { - CXXMethodDecl *OldMD = - dyn_cast(FunTmpl->getTemplatedDecl()); + // specializes). This rule was removed in C++14. + if (auto *NewMD = dyn_cast(FD); + !getLangOpts().CPlusPlus14 && NewMD && NewMD->isConstexpr() && + !isa(NewMD)) { + auto *OldMD = dyn_cast(FunTmpl->getTemplatedDecl()); if (OldMD && OldMD->isConst()) { const FunctionProtoType *FPT = FT->castAs(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index 788e93b56bb3..9e890204c78b 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -89,6 +89,9 @@ struct S { template constexpr T f(); // expected-warning 0-1{{C++14}} expected-note 0-1{{candidate}} template T g() const; // expected-note-re {{candidate template ignored: could not match 'T (){{( __attribute__\(\(thiscall\)\))?}} const' against 'char (){{( __attribute__\(\(thiscall\)\))?}}'}} +#if __cplusplus >= 201402L + // expected-note@-2 {{candidate template ignored: could not match 'T () const' against 'int ()'}} +#endif }; // explicit specialization can differ in constepxr @@ -100,13 +103,17 @@ template <> notlit S::f() const { return notlit(); } #if __cplusplus >= 201402L // expected-error@-2 {{no function template matches}} #endif -template <> constexpr int S::g() { return 0; } // expected-note {{previous}} +template <> constexpr int S::g() { return 0; } #if __cplusplus < 201402L // expected-warning@-2 {{C++14}} +// expected-note@-3 {{previous}} #else -// expected-error@-4 {{does not match any declaration in 'S'}} +// expected-error@-5 {{no function template matches function template specialization 'g'}} +#endif +template <> int S::g() const; +#if __cplusplus < 201402L +// expected-error@-2 {{non-constexpr declaration of 'g' follows constexpr declaration}} #endif -template <> int S::g() const; // expected-error {{non-constexpr declaration of 'g' follows constexpr declaration}} // specializations can drop the 'constexpr' but not the implied 'const'. template <> char S::g() { return 0; } // expected-error {{no function template matches}} template <> double S::g() const { return 0; } // ok diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp new file mode 100644 index 000000000000..2a5748908369 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p12.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify=expected,cxx11 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify=expected,since-cxx14 %s + +struct A { + template + void f0(); + + template<> + constexpr void f0(); // cxx11-error {{conflicting types for 'f0'}} + // cxx11-note@-1 {{previous declaration is here}} + // cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + + template + void f1() const; // since-cxx14-note 2{{candidate template ignored: could not match 'void () const' against 'void ()'}} + + template<> + constexpr void f1(); // since-cxx14-error {{no function template matches function template specialization 'f1'}} + // cxx11-warning@-1 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} +}; + +template<> +constexpr void A::f0(); // cxx11-error {{conflicting types for 'f0'}} + // cxx11-note@-1 {{previous declaration is here}} + // cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + +template<> +constexpr void A::f1(); // since-cxx14-error {{no function template matches function template specialization 'f1'}} + // cxx11-warning@-1 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + +// FIXME: It's unclear whether [temp.expl.spec]p12 is intended to apply to +// members of a class template explicitly specialized for an implicitly +// instantiated specialization of that template. +template +struct B { + void g0(); // since-cxx14-note {{previous declaration is here}} + // cxx11-note@-1 {{member declaration does not match because it is not const qualified}} + + void g1() const; // since-cxx14-note {{member declaration does not match because it is const qualified}} + // cxx11-note@-1 {{previous declaration is here}} + + template + void h0(); // since-cxx14-note {{previous declaration is here}} + + template + void h1() const; // cxx11-note {{previous declaration is here}} +}; + +template<> +constexpr void B::g0(); // since-cxx14-error {{constexpr declaration of 'g0' follows non-constexpr declaration}} + // cxx11-error@-1 {{out-of-line declaration of 'g0' does not match any declaration in 'B'}} + // cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + +template<> +constexpr void B::g1(); // since-cxx14-error {{out-of-line declaration of 'g1' does not match any declaration in 'B'}} + // cxx11-error@-1 {{constexpr declaration of 'g1' follows non-constexpr declaration}} + // cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + +template<> +template +constexpr void B::h0(); // since-cxx14-error {{constexpr declaration of 'h0' follows non-constexpr declaration}} + // cxx11-error@-1 {{out-of-line declaration of 'h0' does not match any declaration in 'B'}} + // cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + +template<> +template +constexpr void B::h1(); // since-cxx14-error {{out-of-line declaration of 'h1' does not match any declaration in 'B'}} + // cxx11-error@-1 {{constexpr declaration of 'h1' follows non-constexpr declaration}} + // cxx11-warning@-2 {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const'}} + + -- GitLab From 6430939baaa6222518d58d9192160312fca09327 Mon Sep 17 00:00:00 2001 From: Chris B Date: Mon, 20 May 2024 13:53:24 -0500 Subject: [PATCH 120/793] [HLSL][CMake] Cache files don't have generator vars (#92793) Doh! CMake cache scripts don't have generator variables set yet, so the script can't depend on the generator variables. Instead I've added a variable that a user can specify to enable the distribution settings. --- clang/cmake/caches/HLSL.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/cmake/caches/HLSL.cmake b/clang/cmake/caches/HLSL.cmake index 27f848fdccf0..ed813f60c9c6 100644 --- a/clang/cmake/caches/HLSL.cmake +++ b/clang/cmake/caches/HLSL.cmake @@ -12,7 +12,7 @@ set(LLVM_ENABLE_PROJECTS "clang;clang-tools-extra" CACHE STRING "") set(CLANG_ENABLE_HLSL On CACHE BOOL "") -if (NOT CMAKE_CONFIGURATION_TYPES) +if (HLSL_ENABLE_DISTRIBUTION) set(LLVM_DISTRIBUTION_COMPONENTS "clang;hlsl-resource-headers;clangd" CACHE STRING "") -- GitLab From 1eb7f055d9ae5d14de8e4f75687dc2cf45511300 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 20 May 2024 21:02:48 +0200 Subject: [PATCH 121/793] CodeGen: Fix libcall names for exp10 on the various darwins (#92520) It's really great that we have the same information duplicated in TargetLibraryInfo and RuntimeLibcalls which both assume everything by default. Should fix issue reported after #92287 --- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 11 ++++- llvm/lib/CodeGen/TargetLoweringBase.cpp | 28 +++++++++++++ .../CodeGen/AArch64/exp10-libcall-names.ll | 39 ++++++++++++++++++ llvm/test/CodeGen/ARM/exp10-libcall-names.ll | 39 ++++++++++++++++++ llvm/test/CodeGen/X86/exp10-libcall-names.ll | 40 +++++++++++++++++++ 5 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/exp10-libcall-names.ll create mode 100644 llvm/test/CodeGen/ARM/exp10-libcall-names.ll create mode 100644 llvm/test/CodeGen/X86/exp10-libcall-names.ll diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 0543c211c497..bfc2273c9425 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -2050,8 +2050,15 @@ SDValue SelectionDAGLegalize::ExpandSPLAT_VECTOR(SDNode *Node) { std::pair SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, TargetLowering::ArgListTy &&Args, bool isSigned) { - SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC), - TLI.getPointerTy(DAG.getDataLayout())); + EVT CodePtrTy = TLI.getPointerTy(DAG.getDataLayout()); + SDValue Callee; + if (const char *LibcallName = TLI.getLibcallName(LC)) + Callee = DAG.getExternalSymbol(LibcallName, CodePtrTy); + else { + Callee = DAG.getUNDEF(CodePtrTy); + DAG.getContext()->emitError(Twine("no libcall available for ") + + Node->getOperationName(&DAG)); + } EVT RetVT = Node->getValueType(0); Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext()); diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp index 09b70cfb7227..82a59918b085 100644 --- a/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -227,6 +227,34 @@ void TargetLoweringBase::InitLibcalls(const Triple &TT) { CallingConv::ARM_AAPCS_VFP); } } + + switch (TT.getOS()) { + case Triple::MacOSX: + if (TT.isMacOSXVersionLT(10, 9)) { + setLibcallName(RTLIB::EXP10_F32, nullptr); + setLibcallName(RTLIB::EXP10_F64, nullptr); + } else { + setLibcallName(RTLIB::EXP10_F32, "__exp10f"); + setLibcallName(RTLIB::EXP10_F64, "__exp10"); + } + break; + case Triple::IOS: + case Triple::TvOS: + case Triple::WatchOS: + case Triple::XROS: + if (!TT.isWatchOS() && + (TT.isOSVersionLT(7, 0) || (TT.isOSVersionLT(9, 0) && TT.isX86()))) { + setLibcallName(RTLIB::EXP10_F32, nullptr); + setLibcallName(RTLIB::EXP10_F64, nullptr); + } else { + setLibcallName(RTLIB::EXP10_F32, "__exp10f"); + setLibcallName(RTLIB::EXP10_F64, "__exp10"); + } + + break; + default: + break; + } } else { setLibcallName(RTLIB::FPEXT_F16_F32, "__gnu_h2f_ieee"); setLibcallName(RTLIB::FPROUND_F32_F16, "__gnu_f2h_ieee"); diff --git a/llvm/test/CodeGen/AArch64/exp10-libcall-names.ll b/llvm/test/CodeGen/AArch64/exp10-libcall-names.ll new file mode 100644 index 000000000000..1220aec447ab --- /dev/null +++ b/llvm/test/CodeGen/AArch64/exp10-libcall-names.ll @@ -0,0 +1,39 @@ +; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck -check-prefix=LINUX %s +; RUN: llc -mtriple=aarch64-apple-macos10.9 < %s | FileCheck -check-prefix=APPLE %s +; RUN: llc -mtriple=aarch64-apple-ios7.0 < %s | FileCheck -check-prefix=APPLE %s +; RUN: llc -mtriple=aarch64-apple-tvos7.0 < %s | FileCheck -check-prefix=APPLE %s +; RUN: llc -mtriple=aarch64-apple-watchos7.0 < %s | FileCheck -check-prefix=APPLE %s +; RUN: llc -mtriple=aarch64-apple-xros7.0 < %s | FileCheck -check-prefix=APPLE %s + +; RUN: not llc -mtriple=aarch64-apple-macos10.8 -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s +; RUN: not llc -mtriple=aarch64-apple-ios6.0 -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s +; RUN: not llc -mtriple=aarch64-apple-tvos6.0 -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s +; RUN: not llc -mtriple=aarch64-apple-xros6.0 -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s + +; Check exp10/exp10f is emitted as __exp10/__exp10f on assorted systems. + +; ERR: no libcall available for fexp10 + +define float @test_exp10_f32(float %x) { +; LINUX-LABEL: test_exp10_f32: +; LINUX: // %bb.0: +; LINUX-NEXT: b exp10f +; +; APPLE-LABEL: test_exp10_f32: +; APPLE: ; %bb.0: +; APPLE-NEXT: b ___exp10f + %ret = call float @llvm.exp10.f32(float %x) + ret float %ret +} + +define double @test_exp10_f64(double %x) { +; LINUX-LABEL: test_exp10_f64: +; LINUX: // %bb.0: +; LINUX-NEXT: b exp10 +; +; APPLE-LABEL: test_exp10_f64: +; APPLE: ; %bb.0: +; APPLE-NEXT: b ___exp10 + %ret = call double @llvm.exp10.f64(double %x) + ret double %ret +} diff --git a/llvm/test/CodeGen/ARM/exp10-libcall-names.ll b/llvm/test/CodeGen/ARM/exp10-libcall-names.ll new file mode 100644 index 000000000000..0ac68b3e8c46 --- /dev/null +++ b/llvm/test/CodeGen/ARM/exp10-libcall-names.ll @@ -0,0 +1,39 @@ +; RUN: llc -mtriple=armv7-linux-gnu < %s | FileCheck -check-prefix=LINUX %s +; RUN: llc -mtriple=armv7-apple-macos10.9 < %s | FileCheck -check-prefix=APPLE %s +; RUN: llc -mtriple=armv7-apple-ios7.0 < %s | FileCheck -check-prefix=APPLE %s +; RUN: llc -mtriple=armv7-apple-tvos7.0 < %s | FileCheck -check-prefix=APPLE %s +; RUN: llc -mtriple=armv7-apple-watchos7.0 < %s | FileCheck -check-prefix=APPLE %s +; RUN: llc -mtriple=armv7-apple-xros7.0 < %s | FileCheck -check-prefix=APPLE %s + +; RUN: not llc -mtriple=armv7-apple-macos10.8 -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s +; RUN: not llc -mtriple=armv7-apple-ios6.0 -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s +; RUN: not llc -mtriple=armv7-apple-tvos6.0 -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s +; RUN: not llc -mtriple=armv7-apple-xros6.0 -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s + +; Check exp10/exp10f is emitted as __exp10/__exp10f on assorted systems. + +; ERR: no libcall available for fexp10 + +define float @test_exp10_f32(float %x) { +; LINUX-LABEL: test_exp10_f32: +; LINUX: @ %bb.0: +; LINUX-NEXT: b exp10f +; +; APPLE-LABEL: test_exp10_f32: +; APPLE: @ %bb.0: +; APPLE-NEXT: b ___exp10f + %ret = call float @llvm.exp10.f32(float %x) + ret float %ret +} + +define double @test_exp10_f64(double %x) { +; LINUX-LABEL: test_exp10_f64: +; LINUX: @ %bb.0: +; LINUX-NEXT: b exp10 +; +; APPLE-LABEL: test_exp10_f64: +; APPLE: @ %bb.0: +; APPLE-NEXT: b ___exp10 + %ret = call double @llvm.exp10.f64(double %x) + ret double %ret +} diff --git a/llvm/test/CodeGen/X86/exp10-libcall-names.ll b/llvm/test/CodeGen/X86/exp10-libcall-names.ll new file mode 100644 index 000000000000..ce26a0e738e9 --- /dev/null +++ b/llvm/test/CodeGen/X86/exp10-libcall-names.ll @@ -0,0 +1,40 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=x86_64-linux-gnu < %s | FileCheck -check-prefix=LINUX %s +; RUN: llc -mtriple=x86_64-apple-macos10.9 < %s | FileCheck -check-prefix=APPLE %s +; RUN: llc -mtriple=x86_64-apple-ios9.0 < %s | FileCheck -check-prefix=APPLE %s +; RUN: llc -mtriple=x86_64-apple-tvos9.0 < %s | FileCheck -check-prefix=APPLE %s +; RUN: llc -mtriple=x86_64-apple-watchos9.0 < %s | FileCheck -check-prefix=APPLE %s +; RUN: llc -mtriple=x86_64-apple-xros9.0 < %s | FileCheck -check-prefix=APPLE %s + +; RUN: not llc -mtriple=x86_64-apple-macos10.8 -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s +; RUN: not llc -mtriple=x86_64-apple-ios8.0 -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s +; RUN: not llc -mtriple=x86_64-apple-tvos8.0 -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s +; RUN: not llc -mtriple=x86_64-apple-xros8.0 -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s + +; Check exp10/exp10f is emitted as __exp10/__exp10f on assorted systems. + +; ERR: no libcall available for fexp10 + +define float @test_exp10_f32(float %x) { +; LINUX-LABEL: test_exp10_f32: +; LINUX: # %bb.0: +; LINUX-NEXT: jmp exp10f@PLT # TAILCALL +; +; APPLE-LABEL: test_exp10_f32: +; APPLE: ## %bb.0: +; APPLE-NEXT: jmp ___exp10f ## TAILCALL + %ret = call float @llvm.exp10.f32(float %x) + ret float %ret +} + +define double @test_exp10_f64(double %x) { +; LINUX-LABEL: test_exp10_f64: +; LINUX: # %bb.0: +; LINUX-NEXT: jmp exp10@PLT # TAILCALL +; +; APPLE-LABEL: test_exp10_f64: +; APPLE: ## %bb.0: +; APPLE-NEXT: jmp ___exp10 ## TAILCALL + %ret = call double @llvm.exp10.f64(double %x) + ret double %ret +} -- GitLab From e1c06c380ce01a4524df8061171e63cad010e4e6 Mon Sep 17 00:00:00 2001 From: Leon Clark Date: Mon, 20 May 2024 20:32:53 +0100 Subject: [PATCH 122/793] [AMDGPU] Fix error in #88512. (#92770) Fixes error in GlobalISel CTLZ lowering caused by [#88512](https://github.com/llvm/llvm-project/pull/88512). --------- Co-authored-by: Leon Clark --- .../lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp | 2 +- .../GlobalISel/legalize-ctlz-zero-undef.mir | 16 ++-- llvm/test/CodeGen/AMDGPU/ctlz_zero_undef.ll | 76 ++++++++++++------- 3 files changed, 57 insertions(+), 37 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp index 15a4b6796880..a771b421e77a 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -4168,7 +4168,7 @@ bool AMDGPULegalizerInfo::legalizeCTLZ_ZERO_UNDEF(MachineInstr &MI, auto ShiftAmt = B.buildConstant(S32, 32u - NumBits); auto Extend = B.buildAnyExt(S32, {Src}).getReg(0u); - auto Shift = B.buildLShr(S32, {Extend}, ShiftAmt); + auto Shift = B.buildShl(S32, Extend, ShiftAmt); auto Ctlz = B.buildInstr(AMDGPU::G_AMDGPU_FFBH_U32, {S32}, {Shift}); B.buildTrunc(Dst, Ctlz); MI.eraseFromParent(); diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ctlz-zero-undef.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ctlz-zero-undef.mir index 7748b481cf5b..85cfb9b320f1 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ctlz-zero-undef.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ctlz-zero-undef.mir @@ -82,8 +82,8 @@ body: | ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 - ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[COPY]], [[C]](s32) - ; CHECK-NEXT: [[AMDGPU_FFBH_U32:%[0-9]+]]:_(s32) = G_AMDGPU_FFBH_U32 [[LSHR]](s32) + ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY]], [[C]](s32) + ; CHECK-NEXT: [[AMDGPU_FFBH_U32:%[0-9]+]]:_(s32) = G_AMDGPU_FFBH_U32 [[SHL]](s32) ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[AMDGPU_FFBH_U32]], [[C1]] ; CHECK-NEXT: $vgpr0 = COPY [[AND]](s32) @@ -147,10 +147,10 @@ body: | ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(s32) = G_BITCAST [[COPY]](<2 x s16>) ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[BITCAST]], [[C]](s32) - ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(s32) = G_LSHR [[BITCAST]], [[C]](s32) - ; CHECK-NEXT: [[AMDGPU_FFBH_U32:%[0-9]+]]:_(s32) = G_AMDGPU_FFBH_U32 [[LSHR1]](s32) - ; CHECK-NEXT: [[LSHR2:%[0-9]+]]:_(s32) = G_LSHR [[LSHR]], [[C]](s32) - ; CHECK-NEXT: [[AMDGPU_FFBH_U321:%[0-9]+]]:_(s32) = G_AMDGPU_FFBH_U32 [[LSHR2]](s32) + ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[BITCAST]], [[C]](s32) + ; CHECK-NEXT: [[AMDGPU_FFBH_U32:%[0-9]+]]:_(s32) = G_AMDGPU_FFBH_U32 [[SHL]](s32) + ; CHECK-NEXT: [[SHL2:%[0-9]+]]:_(s32) = G_SHL [[LSHR]], [[C]](s32) + ; CHECK-NEXT: [[AMDGPU_FFBH_U321:%[0-9]+]]:_(s32) = G_AMDGPU_FFBH_U32 [[SHL2]](s32) ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[AMDGPU_FFBH_U32]], [[C1]] ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[AMDGPU_FFBH_U321]], [[C1]] @@ -175,8 +175,8 @@ body: | ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 25 - ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[COPY]], [[C]](s32) - ; CHECK-NEXT: [[FFBH:%[0-9]+]]:_(s32) = G_AMDGPU_FFBH_U32 [[LSHR]](s32) + ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY]], [[C]](s32) + ; CHECK-NEXT: [[FFBH:%[0-9]+]]:_(s32) = G_AMDGPU_FFBH_U32 [[SHL]](s32) ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 127 ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[FFBH]], [[C1]] ; CHECK-NEXT: $vgpr0 = COPY [[AND]](s32) diff --git a/llvm/test/CodeGen/AMDGPU/ctlz_zero_undef.ll b/llvm/test/CodeGen/AMDGPU/ctlz_zero_undef.ll index d94a27e8c020..756b81909968 100644 --- a/llvm/test/CodeGen/AMDGPU/ctlz_zero_undef.ll +++ b/llvm/test/CodeGen/AMDGPU/ctlz_zero_undef.ll @@ -377,7 +377,7 @@ define amdgpu_kernel void @s_ctlz_zero_undef_i8_with_select(ptr addrspace(1) noa ; GFX9-GISEL-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x24 ; GFX9-GISEL-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-GISEL-NEXT: s_waitcnt lgkmcnt(0) -; GFX9-GISEL-NEXT: s_lshr_b32 s0, s4, 24 +; GFX9-GISEL-NEXT: s_lshl_b32 s0, s4, 24 ; GFX9-GISEL-NEXT: s_flbit_i32_b32 s0, s0 ; GFX9-GISEL-NEXT: v_mov_b32_e32 v0, s0 ; GFX9-GISEL-NEXT: global_store_byte v1, v0, s[2:3] @@ -452,7 +452,7 @@ define amdgpu_kernel void @s_ctlz_zero_undef_i16_with_select(ptr addrspace(1) no ; GFX9-GISEL-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x24 ; GFX9-GISEL-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-GISEL-NEXT: s_waitcnt lgkmcnt(0) -; GFX9-GISEL-NEXT: s_lshr_b32 s0, s4, 16 +; GFX9-GISEL-NEXT: s_lshl_b32 s0, s4, 16 ; GFX9-GISEL-NEXT: s_flbit_i32_b32 s0, s0 ; GFX9-GISEL-NEXT: v_mov_b32_e32 v0, s0 ; GFX9-GISEL-NEXT: global_store_short v1, v0, s[2:3] @@ -655,7 +655,8 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i8_with_select(ptr addrspace(1) noa ; GFX9-GISEL-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-GISEL-NEXT: global_load_ubyte v1, v0, s[2:3] ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v2, v1 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v2, 24, v1 +; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v2, v2 ; GFX9-GISEL-NEXT: v_and_b32_e32 v2, 0xff, v2 ; GFX9-GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v1 ; GFX9-GISEL-NEXT: v_cndmask_b32_e32 v1, 32, v2, vcc @@ -760,7 +761,8 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i16_with_select(ptr addrspace(1) no ; GFX9-GISEL-NEXT: global_load_ubyte v2, v0, s[2:3] offset:1 ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) ; GFX9-GISEL-NEXT: v_lshl_or_b32 v1, v2, 8, v1 -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v2, v1 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v2, 16, v1 +; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v2, v2 ; GFX9-GISEL-NEXT: v_and_b32_e32 v2, 0xffff, v2 ; GFX9-GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v1 ; GFX9-GISEL-NEXT: v_cndmask_b32_e32 v1, 32, v2, vcc @@ -1167,7 +1169,8 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i8(ptr addrspace(1) noalias %out, p ; GFX9-GISEL-NEXT: global_load_ubyte v0, v[0:1], off ; GFX9-GISEL-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v0, v0 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v0, 24, v0 +; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v0, v0 ; GFX9-GISEL-NEXT: global_store_byte v1, v0, s[0:1] ; GFX9-GISEL-NEXT: s_endpgm %tid = call i32 @llvm.amdgcn.workitem.id.x() @@ -1705,8 +1708,9 @@ define amdgpu_kernel void @v_ctlz_zero_undef_i8_sel_eq_neg1(ptr addrspace(1) noa ; GFX9-GISEL-NEXT: global_load_ubyte v0, v[0:1], off ; GFX9-GISEL-NEXT: v_mov_b32_e32 v1, 0 ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v2, v0 -; GFX9-GISEL-NEXT: v_cmp_eq_u32_sdwa s[2:3], v0, v1 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v2, 24, v0 +; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v2, v2 +; GFX9-GISEL-NEXT: v_cmp_eq_u32_sdwa s[2:3], v0, v1 src0_sel:BYTE_0 src1_sel:DWORD ; GFX9-GISEL-NEXT: v_cndmask_b32_e64 v0, v2, -1, s[2:3] ; GFX9-GISEL-NEXT: global_store_byte v1, v0, s[0:1] ; GFX9-GISEL-NEXT: s_endpgm @@ -2186,7 +2190,7 @@ define i7 @v_ctlz_zero_undef_i7(i7 %val) { ; GFX9-GISEL-LABEL: v_ctlz_zero_undef_i7: ; GFX9-GISEL: ; %bb.0: ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-GISEL-NEXT: v_lshrrev_b32_e32 v0, 25, v0 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v0, 25, v0 ; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v0, v0 ; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31] %ctlz = call i7 @llvm.ctlz.i7(i7 %val, i1 true) @@ -2278,7 +2282,7 @@ define amdgpu_kernel void @s_ctlz_zero_undef_i18(ptr addrspace(1) noalias %out, ; GFX9-GISEL-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x24 ; GFX9-GISEL-NEXT: v_mov_b32_e32 v0, 0 ; GFX9-GISEL-NEXT: s_waitcnt lgkmcnt(0) -; GFX9-GISEL-NEXT: s_lshr_b32 s0, s4, 14 +; GFX9-GISEL-NEXT: s_lshl_b32 s0, s4, 14 ; GFX9-GISEL-NEXT: s_flbit_i32_b32 s0, s0 ; GFX9-GISEL-NEXT: s_and_b32 s0, s0, 0x3ffff ; GFX9-GISEL-NEXT: s_lshr_b32 s1, s0, 16 @@ -2317,7 +2321,7 @@ define i18 @v_ctlz_zero_undef_i18(i18 %val) { ; GFX9-GISEL-LABEL: v_ctlz_zero_undef_i18: ; GFX9-GISEL: ; %bb.0: ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-GISEL-NEXT: v_lshrrev_b32_e32 v0, 14, v0 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v0, 14, v0 ; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v0, v0 ; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31] %ctlz = call i18 @llvm.ctlz.i18(i18 %val, i1 true) @@ -2355,8 +2359,8 @@ define <2 x i18> @v_ctlz_zero_undef_v2i18(<2 x i18> %val) { ; GFX9-GISEL-LABEL: v_ctlz_zero_undef_v2i18: ; GFX9-GISEL: ; %bb.0: ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-GISEL-NEXT: v_lshrrev_b32_e32 v0, 14, v0 -; GFX9-GISEL-NEXT: v_lshrrev_b32_e32 v1, 14, v1 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v0, 14, v0 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v1, 14, v1 ; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v0, v0 ; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v1, v1 ; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31] @@ -2394,10 +2398,13 @@ define <2 x i16> @v_ctlz_zero_undef_v2i16(<2 x i16> %val) { ; GFX9-GISEL-LABEL: v_ctlz_zero_undef_v2i16: ; GFX9-GISEL: ; %bb.0: ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v0, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; GFX9-GISEL-NEXT: s_flbit_i32_b32 s4, 0 +; GFX9-GISEL-NEXT: v_lshrrev_b32_e32 v1, 16, v0 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v0, v0 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v1, 16, v1 +; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v1, v1 ; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0xffff, v0 -; GFX9-GISEL-NEXT: v_lshl_or_b32 v0, s4, 16, v0 +; GFX9-GISEL-NEXT: v_lshl_or_b32 v0, v1, 16, v0 ; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31] %ctlz = call <2 x i16> @llvm.ctlz.v2i16(<2 x i16> %val, i1 true) ret <2 x i16> %ctlz @@ -2439,11 +2446,15 @@ define <3 x i16> @v_ctlz_zero_undef_v3i16(<3 x i16> %val) { ; GFX9-GISEL-LABEL: v_ctlz_zero_undef_v3i16: ; GFX9-GISEL: ; %bb.0: ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v0, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; GFX9-GISEL-NEXT: s_flbit_i32_b32 s4, 0 +; GFX9-GISEL-NEXT: v_lshrrev_b32_e32 v2, 16, v0 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v0, v0 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v2, 16, v2 +; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v2, v2 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v1, 16, v1 ; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0xffff, v0 -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v1, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; GFX9-GISEL-NEXT: v_lshl_or_b32 v0, s4, 16, v0 +; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v1, v1 +; GFX9-GISEL-NEXT: v_lshl_or_b32 v0, v2, 16, v0 ; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31] %ctlz = call <3 x i16> @llvm.ctlz.v3i16(<3 x i16> %val, i1 true) ret <3 x i16> %ctlz @@ -2492,13 +2503,20 @@ define <4 x i16> @v_ctlz_zero_undef_v4i16(<4 x i16> %val) { ; GFX9-GISEL-LABEL: v_ctlz_zero_undef_v4i16: ; GFX9-GISEL: ; %bb.0: ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v0, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v1, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; GFX9-GISEL-NEXT: s_flbit_i32_b32 s4, 0 +; GFX9-GISEL-NEXT: v_lshrrev_b32_e32 v2, 16, v0 +; GFX9-GISEL-NEXT: v_lshrrev_b32_e32 v3, 16, v1 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v1, 16, v1 +; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v0, v0 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v2, 16, v2 +; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v1, v1 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v3, 16, v3 +; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v2, v2 +; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v3, v3 ; GFX9-GISEL-NEXT: v_and_b32_e32 v0, 0xffff, v0 ; GFX9-GISEL-NEXT: v_and_b32_e32 v1, 0xffff, v1 -; GFX9-GISEL-NEXT: v_lshl_or_b32 v0, s4, 16, v0 -; GFX9-GISEL-NEXT: v_lshl_or_b32 v1, s4, 16, v1 +; GFX9-GISEL-NEXT: v_lshl_or_b32 v0, v2, 16, v0 +; GFX9-GISEL-NEXT: v_lshl_or_b32 v1, v3, 16, v1 ; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31] %ctlz = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> %val, i1 true) ret <4 x i16> %ctlz @@ -2536,8 +2554,10 @@ define <2 x i8> @v_ctlz_zero_undef_v2i8(<2 x i8> %val) { ; GFX9-GISEL-LABEL: v_ctlz_zero_undef_v2i8: ; GFX9-GISEL: ; %bb.0: ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v0, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 -; GFX9-GISEL-NEXT: v_ffbh_u32_sdwa v1, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v0, 24, v0 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v1, 24, v1 +; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v0, v0 +; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v1, v1 ; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31] %ctlz = call <2 x i8> @llvm.ctlz.v2i8(<2 x i8> %val, i1 true) ret <2 x i8> %ctlz @@ -2579,8 +2599,8 @@ define <2 x i7> @v_ctlz_zero_undef_v2i7(<2 x i7> %val) { ; GFX9-GISEL-LABEL: v_ctlz_zero_undef_v2i7: ; GFX9-GISEL: ; %bb.0: ; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-GISEL-NEXT: v_lshrrev_b32_e32 v0, 25, v0 -; GFX9-GISEL-NEXT: v_lshrrev_b32_e32 v1, 25, v1 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v0, 25, v0 +; GFX9-GISEL-NEXT: v_lshlrev_b32_e32 v1, 25, v1 ; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v0, v0 ; GFX9-GISEL-NEXT: v_ffbh_u32_e32 v1, v1 ; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31] -- GitLab From fdd245ad856f85019bb408ed5c14984823e7077f Mon Sep 17 00:00:00 2001 From: Hugo Trachino Date: Mon, 20 May 2024 20:46:41 +0100 Subject: [PATCH 123/793] [MLIR][Vector] Implement transferXXPermutationLowering as MaskableOpRewritePattern (#91987) * Implements `TransferWritePermutationLowering`, `TransferReadPermutationLowering` and `TransferWriteNonPermutationLowering` as a MaskableOpRewritePattern. Allowing to exit gracefully when such use of a xferOp is inside a `vector::MaskOp` * Updates MaskableOpRewritePattern to handle MemRefs and buffer semantics providing empty `Value()` as a return value for `matchAndRewriteMaskableOp` now represents successful rewriting without value to replace the original op. Split of https://github.com/llvm/llvm-project/pull/90835 --- .../mlir/Dialect/Vector/Utils/VectorUtils.h | 9 ++- .../Vector/Transforms/LowerVectorTransfer.cpp | 70 +++++++++++------ .../vector-transfer-permutation-lowering.mlir | 76 +++++++++++++++++++ 3 files changed, 130 insertions(+), 25 deletions(-) diff --git a/mlir/include/mlir/Dialect/Vector/Utils/VectorUtils.h b/mlir/include/mlir/Dialect/Vector/Utils/VectorUtils.h index 030be328e97f..9c83acc76e77 100644 --- a/mlir/include/mlir/Dialect/Vector/Utils/VectorUtils.h +++ b/mlir/include/mlir/Dialect/Vector/Utils/VectorUtils.h @@ -157,7 +157,14 @@ private: if (failed(newOp)) return failure(); - rewriter.replaceOp(rootOp, *newOp); + // Rewriting succeeded but there are no values to replace. + if (rootOp->getNumResults() == 0) { + rewriter.eraseOp(rootOp); + } else { + assert(*newOp != Value() && + "Cannot replace an op's use with an empty value."); + rewriter.replaceOp(rootOp, *newOp); + } return success(); } diff --git a/mlir/lib/Dialect/Vector/Transforms/LowerVectorTransfer.cpp b/mlir/lib/Dialect/Vector/Transforms/LowerVectorTransfer.cpp index b30b43d70bf0..c59012266ceb 100644 --- a/mlir/lib/Dialect/Vector/Transforms/LowerVectorTransfer.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/LowerVectorTransfer.cpp @@ -90,14 +90,19 @@ namespace { /// Note that an alternative is to transform it to linalg.transpose + /// vector.transfer_read to do the transpose in memory instead. struct TransferReadPermutationLowering - : public OpRewritePattern { - using OpRewritePattern::OpRewritePattern; + : public MaskableOpRewritePattern { + using MaskableOpRewritePattern::MaskableOpRewritePattern; - LogicalResult matchAndRewrite(vector::TransferReadOp op, - PatternRewriter &rewriter) const override { + FailureOr + matchAndRewriteMaskableOp(vector::TransferReadOp op, + MaskingOpInterface maskOp, + PatternRewriter &rewriter) const override { // TODO: support 0-d corner case. if (op.getTransferRank() == 0) return rewriter.notifyMatchFailure(op, "0-d corner case not supported"); + // TODO: Support transfer_read inside MaskOp case. + if (maskOp) + return rewriter.notifyMatchFailure(op, "Masked case not supported"); SmallVector permutation; AffineMap map = op.getPermutationMap(); @@ -142,9 +147,9 @@ struct TransferReadPermutationLowering // Transpose result of transfer_read. SmallVector transposePerm(permutation.begin(), permutation.end()); - rewriter.replaceOpWithNewOp(op, newRead, - transposePerm); - return success(); + return rewriter + .create(op.getLoc(), newRead, transposePerm) + .getResult(); } }; @@ -165,14 +170,19 @@ struct TransferReadPermutationLowering /// %v = vector.transfer_write %tmp ... /// permutation_map: (d0, d1, d2, d3) -> (d2, d3) struct TransferWritePermutationLowering - : public OpRewritePattern { - using OpRewritePattern::OpRewritePattern; + : public MaskableOpRewritePattern { + using MaskableOpRewritePattern::MaskableOpRewritePattern; - LogicalResult matchAndRewrite(vector::TransferWriteOp op, - PatternRewriter &rewriter) const override { + FailureOr + matchAndRewriteMaskableOp(vector::TransferWriteOp op, + MaskingOpInterface maskOp, + PatternRewriter &rewriter) const override { // TODO: support 0-d corner case. if (op.getTransferRank() == 0) return rewriter.notifyMatchFailure(op, "0-d corner case not supported"); + // TODO: Support transfer_write inside MaskOp case. + if (maskOp) + return rewriter.notifyMatchFailure(op, "Masked case not supported"); SmallVector permutation; AffineMap map = op.getPermutationMap(); @@ -207,11 +217,14 @@ struct TransferWritePermutationLowering op.getLoc(), op.getVector(), indices); auto newMap = AffineMap::getMinorIdentityMap( map.getNumDims(), map.getNumResults(), rewriter.getContext()); - rewriter.replaceOpWithNewOp( - op, newVec, op.getSource(), op.getIndices(), AffineMapAttr::get(newMap), - op.getMask(), newInBoundsAttr); - - return success(); + auto newWrite = rewriter.create( + op.getLoc(), newVec, op.getSource(), op.getIndices(), + AffineMapAttr::get(newMap), op.getMask(), newInBoundsAttr); + if (newWrite.hasPureTensorSemantics()) + return newWrite.getResult(); + // In the memref case there's no return value. Use empty value to signal + // success. + return Value(); } }; @@ -231,14 +244,19 @@ struct TransferWritePermutationLowering /// vector<1x8x16xf32> /// ``` struct TransferWriteNonPermutationLowering - : public OpRewritePattern { - using OpRewritePattern::OpRewritePattern; + : public MaskableOpRewritePattern { + using MaskableOpRewritePattern::MaskableOpRewritePattern; - LogicalResult matchAndRewrite(vector::TransferWriteOp op, - PatternRewriter &rewriter) const override { + FailureOr + matchAndRewriteMaskableOp(vector::TransferWriteOp op, + MaskingOpInterface maskOp, + PatternRewriter &rewriter) const override { // TODO: support 0-d corner case. if (op.getTransferRank() == 0) return rewriter.notifyMatchFailure(op, "0-d corner case not supported"); + // TODO: Support transfer_write inside MaskOp case. + if (maskOp) + return rewriter.notifyMatchFailure(op, "Masked case not supported"); SmallVector permutation; AffineMap map = op.getPermutationMap(); @@ -285,10 +303,14 @@ struct TransferWriteNonPermutationLowering newInBoundsValues.push_back(op.isDimInBounds(i)); } ArrayAttr newInBoundsAttr = rewriter.getBoolArrayAttr(newInBoundsValues); - rewriter.replaceOpWithNewOp( - op, newVec, op.getSource(), op.getIndices(), AffineMapAttr::get(newMap), - newMask, newInBoundsAttr); - return success(); + auto newWrite = rewriter.create( + op.getLoc(), newVec, op.getSource(), op.getIndices(), + AffineMapAttr::get(newMap), newMask, newInBoundsAttr); + if (newWrite.hasPureTensorSemantics()) + return newWrite.getResult(); + // In the memref case there's no return value. Use empty value to signal + // success. + return Value(); } }; diff --git a/mlir/test/Dialect/Vector/vector-transfer-permutation-lowering.mlir b/mlir/test/Dialect/Vector/vector-transfer-permutation-lowering.mlir index e48af3cd7aac..349dc1ab31d4 100644 --- a/mlir/test/Dialect/Vector/vector-transfer-permutation-lowering.mlir +++ b/mlir/test/Dialect/Vector/vector-transfer-permutation-lowering.mlir @@ -46,6 +46,51 @@ func.func @permutation_with_mask_xfer_write_scalable(%arg0: vector<4x[8]xi16>, % return } +// transfer_write in MaskOp case not supported. +// CHECK-LABEL: func @masked_permutation_xfer_write_fixed_width +// CHECK-SAME: %[[ARG_0:.*]]: tensor, +// CHECK-SAME: %[[ARG_1:.*]]: vector<16xf32>, +// CHECK-SAME: %[[IDX:.*]]: index, +// CHECK-SAME: %[[MASK:.*]]: vector<16xi1> +// CHECK-NOT: vector.transpose +// CHECK: %[[RES:.*]] = vector.mask %[[MASK]] { vector.transfer_write %[[ARG_1]], %[[ARG_0]]{{.*}} vector<16xf32>, tensor } : vector<16xi1> -> tensor +func.func @masked_permutation_xfer_write_fixed_width(%t: tensor, %val: vector<16xf32>, %idx: index, %mask: vector<16xi1>) -> tensor { + %r = vector.mask %mask { vector.transfer_write %val, %t[%idx, %idx] {permutation_map = affine_map<(d0, d1) -> (d0)>} : vector<16xf32>, tensor } : vector<16xi1> -> tensor + return %r : tensor +} + +// CHECK-LABEL: func.func @masked_permutation_xfer_write_scalable( +// CHECK-SAME: %[[ARG_0:.*]]: vector<4x[8]xi16>, +// CHECK-SAME: %[[ARG_1:.*]]: tensor, +// CHECK-SAME: %[[MASK:.*]]: vector<4x[8]xi1>) +// CHECK-SAME: -> tensor { +// CHECK-NOT: vector.transpose +// CHECK: %[[R:.*]] = vector.mask %[[MASK]] { vector.transfer_write %[[ARG_0]], %[[ARG_1]]{{.*}} : vector<4x[8]xi16>, tensor } : vector<4x[8]xi1> -> tensor +func.func @masked_permutation_xfer_write_scalable(%arg0: vector<4x[8]xi16>, %t: tensor, %mask: vector<4x[8]xi1>) -> tensor { + %c0 = arith.constant 0 : index + %r = vector.mask %mask { vector.transfer_write %arg0, %t[%c0, %c0, %c0, %c0] {in_bounds = [true, true], permutation_map = affine_map<(d0, d1, d2, d3) -> (d1, d2)> +} : vector<4x[8]xi16>, tensor } : vector<4x[8]xi1> -> tensor + + return %r : tensor +} + +// transfer_write in MaskOp case not supported. +// CHECK-LABEL: func @masked_non_permutation_xfer_write_fixed_width +// CHECK-SAME: %[[ARG0:.*]]: tensor +// CHECK-SAME: %[[ARG1:.*]]: vector<14x8x16xf32> +// CHECK-SAME: %[[IDX:.*]]: index) -> tensor +// CHECK-NOT: vector.broadcast +// CHECK: %[[masked1:.*]] = vector.mask %0 { vector.transfer_write %[[ARG1]], %[[ARG0]]{{.*}} : vector<14x8x16xf32>, tensor } : vector<14x8x16xi1> -> tensor +func.func @masked_non_permutation_xfer_write_fixed_width( + %arg0 : tensor, + %v1 : vector<14x8x16xf32>, %dim : index) -> tensor { + %c0 = arith.constant 0 : index + %mask = vector.create_mask %dim, %dim, %dim : vector<14x8x16xi1> + %0 = vector.mask %mask { vector.transfer_write %v1, %arg0[%c0, %c0, %c0, %c0] {in_bounds = [false, false, true], permutation_map = affine_map<(d0, d1, d2, d3) -> (d0, d1, d3)>} : vector<14x8x16xf32>, tensor } : vector<14x8x16xi1> -> tensor + + return %0 : tensor +} + ///---------------------------------------------------------------------------------------- /// vector.transfer_read ///---------------------------------------------------------------------------------------- @@ -101,6 +146,37 @@ func.func @permutation_with_mask_xfer_read_scalable(%mem: memref, %dim_ return %1 : vector<8x[4]x2xf32> } +// transfer_read in MaskOp case not supported. +// CHECK-LABEL: func @masked_permutation_xfer_read_fixed_width +// CHECK-SAME: %[[ARG_0:.*]]: tensor, +// CHECK-SAME: %[[ARG_1:.*]]: vector<4x1xi1> +// CHECK-NOT: vector.transpose +// CHECK: vector.mask %[[ARG_1]] { vector.transfer_read %[[ARG_0]]{{.*}}: tensor, vector<1x4x4xf32> } : vector<4x1xi1> -> vector<1x4x4xf32> +func.func @masked_permutation_xfer_read_fixed_width(%arg0: tensor, %mask : vector<4x1xi1>) { + %cst = arith.constant 0.000000e+00 : f32 + %c0 = arith.constant 0 : index + %3 = vector.mask %mask { vector.transfer_read %arg0[%c0, %c0], %cst {permutation_map = affine_map<(d0, d1) -> (d1, 0, d0)>} : tensor, vector<1x4x4xf32> } : vector<4x1xi1> -> vector<1x4x4xf32> + call @test.some_use(%3) : (vector<1x4x4xf32>) -> () + return +} +func.func private @test.some_use(vector<1x4x4xf32>) + +// CHECK-LABEL: func.func @masked_permutation_xfer_read_scalable( +// CHECK-SAME: %[[ARG_0:.*]]: tensor, +// CHECK-SAME: %[[MASK:.*]]: vector<2x[4]xi1>) -> vector<8x[4]x2xf32> { +// CHECK-NOT: vector.transpose +// CHECK: %[[T_READ:.*]] = vector.mask %[[MASK]] { vector.transfer_read %[[ARG_0]]{{.*}} : tensor, vector<8x[4]x2xf32> } : vector<2x[4]xi1> -> vector<8x[4]x2xf32> +func.func @masked_permutation_xfer_read_scalable(%t: tensor, %mask : vector<2x[4]xi1>) -> vector<8x[4]x2xf32> { + + %c0 = arith.constant 0 : index + %cst_0 = arith.constant 0.000000e+00 : f32 + + %1 = vector.mask %mask { vector.transfer_read %t[%c0, %c0], %cst_0 + {in_bounds = [true, true, true], permutation_map = affine_map<(d0, d1) -> (0, d1, d0)>} + : tensor, vector<8x[4]x2xf32> } :vector<2x[4]xi1> -> vector<8x[4]x2xf32> + return %1 : vector<8x[4]x2xf32> +} + module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%module_op: !transform.any_op {transform.readonly}) { %f = transform.structured.match ops{["func.func"]} in %module_op -- GitLab From c1d5cc99c6ba8e897ea145dbb2221a155b5e3e5a Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Mon, 20 May 2024 13:03:31 -0700 Subject: [PATCH 124/793] [LangRef] Try to formalize the definition of "odr" in LLVM IR. (#92619) The current definition is a bit fuzzy... replace it with something that's somewhat rigorous. For functions, the definition is pretty narrow; as a consequence of language-level non-determinism, it's impossible to tell whether two functions are equivalent, so just embrace the non-determinism. For constants, we're pretty strict; otherwise you end up concluding constants can actually change value, which is bad for alias analysis. I think C++ standard don't allow any non-deterministic operations in constants, so we should be okay there? Poison is per-byte to allow some ambiguity in the way padding is defined. --- llvm/docs/LangRef.rst | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index e2f4d8bfcaee..358eb4b86792 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -290,13 +290,17 @@ linkage: symbol is weak until linked, if not linked, the symbol becomes null instead of being an undefined reference. ``linkonce_odr``, ``weak_odr`` - Some languages allow differing globals to be merged, such as two - functions with different semantics. Other languages, such as - ``C++``, ensure that only equivalent globals are ever merged (the - "one definition rule" --- "ODR"). Such languages can use the - ``linkonce_odr`` and ``weak_odr`` linkage types to indicate that the - global will only be merged with equivalent globals. These linkage - types are otherwise the same as their non-``odr`` versions. + The ``odr`` suffix indicates that all globals defined with the given name + are equivalent, along the lines of the C++ "one definition rule" ("ODR"). + Informally, this means we can inline functions and fold loads of constants. + + Formally, use the following definition: when an ``odr`` function is + called, one of the definitions is non-deterministically chosen to run. For + ``odr`` variables, if any byte in the value is not equal in all + initializers, that byte is a :ref:`poison value `. For + aliases and ifuncs, apply the rule for the underlying function or variable. + + These linkage types are otherwise the same as their non-``odr`` versions. ``external`` If none of the above identifiers are used, the global is externally visible, meaning that it participates in linkage and can be used to -- GitLab From 0da1a6ceb595fa91e3af20bf7f304ba275526f3c Mon Sep 17 00:00:00 2001 From: Jeremy Kun Date: Mon, 20 May 2024 13:09:10 -0700 Subject: [PATCH 125/793] [mlir][polynomial] split polynomial types tablegen (#92805) Similar to https://github.com/llvm/llvm-project/pull/92613, but for types. Co-authored-by: Jeremy Kun --- .../mlir/Dialect/Polynomial/IR/Polynomial.td | 19 ++--------- .../Dialect/Polynomial/IR/PolynomialTypes.td | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+), 17 deletions(-) create mode 100644 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.td diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.td b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.td index 294f58ae084b..3ef899d3376b 100644 --- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.td +++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.td @@ -1,4 +1,4 @@ -//===- PolynomialOps.td - Polynomial dialect ---------------*- tablegen -*-===// +//===- Polynomial.td - Polynomial dialect ------------------*- tablegen -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -15,22 +15,7 @@ include "mlir/Interfaces/InferTypeOpInterface.td" include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/Dialect/Polynomial/IR/PolynomialDialect.td" include "mlir/Dialect/Polynomial/IR/PolynomialAttributes.td" - -class Polynomial_Type - : TypeDef { - let mnemonic = typeMnemonic; -} - -def Polynomial_PolynomialType : Polynomial_Type<"Polynomial", "polynomial"> { - let summary = "An element of a polynomial ring."; - let description = [{ - A type for polynomials in a polynomial quotient ring. - }]; - let parameters = (ins Polynomial_RingAttr:$ring); - let assemblyFormat = "`<` struct(params) `>`"; -} - -def PolynomialLike: TypeOrContainer; +include "mlir/Dialect/Polynomial/IR/PolynomialTypes.td" class Polynomial_Op traits = []> : Op { diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.td b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.td new file mode 100644 index 000000000000..89e406183e0b --- /dev/null +++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.td @@ -0,0 +1,32 @@ +//===- PolynomialTypes.td - Polynomial types ---------------*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef POLYNOMIAL_TYPES +#define POLYNOMIAL_TYPES + +include "mlir/Dialect/Polynomial/IR/PolynomialAttributes.td" +include "mlir/Dialect/Polynomial/IR/PolynomialDialect.td" + +class Polynomial_Type + : TypeDef { + let mnemonic = typeMnemonic; +} + +def Polynomial_PolynomialType : Polynomial_Type<"Polynomial", "polynomial"> { + let summary = "An element of a polynomial ring."; + let description = [{ + A type for polynomials in a polynomial quotient ring. + }]; + let parameters = (ins Polynomial_RingAttr:$ring); + let assemblyFormat = "`<` struct(params) `>`"; +} + +def PolynomialLike: TypeOrContainer; + + +#endif // POLYNOMIAL_TYPES -- GitLab From 3cb1fe60fb00ba3761e34866ffc93c7d7a0b509d Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 20 May 2024 22:23:02 +0200 Subject: [PATCH 126/793] AMDGPU: Don't fold rootn(x, 1) to input for strictfp functions (#92595) We need to insert a constrained canonicalize. Depends #92594 --- llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp | 11 ++++++++--- .../CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll | 6 ++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp b/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp index 0a5fbf5034c0..47de1791dae3 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp @@ -1163,14 +1163,19 @@ bool AMDGPULibCalls::fold_rootn(FPMathOperator *FPOp, IRBuilder<> &B, if (!match(opr1, m_APIntAllowPoison(CINT))) return false; + Function *Parent = B.GetInsertBlock()->getParent(); + int ci_opr1 = (int)CINT->getSExtValue(); - if (ci_opr1 == 1) { // rootn(x, 1) = x - LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << *opr0 << "\n"); + if (ci_opr1 == 1 && !Parent->hasFnAttribute(Attribute::StrictFP)) { + // rootn(x, 1) = x + // + // TODO: Insert constrained canonicalize for strictfp case. + LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << *opr0 << '\n'); replaceCall(FPOp, opr0); return true; } - Module *M = B.GetInsertBlock()->getModule(); + Module *M = Parent->getParent(); if (ci_opr1 == 2) { // rootn(x, 2) = sqrt(x) if (FunctionCallee FPExpr = getFunction(M, AMDGPULibFunc(AMDGPULibFunc::EI_SQRT, FInfo))) { diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll index f79983e2491a..d75517cb2687 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll @@ -511,7 +511,8 @@ define float @test_rootn_f32__y_1__strictfp(float %x) #1 { ; CHECK-LABEL: define float @test_rootn_f32__y_1__strictfp( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: ret float [[X]] +; CHECK-NEXT: [[CALL:%.*]] = tail call float @_Z5rootnfi(float [[X]], i32 1) #[[ATTR0]] +; CHECK-NEXT: ret float [[CALL]] ; entry: %call = tail call float @_Z5rootnfi(float %x, i32 1) #1 @@ -533,7 +534,8 @@ define <2 x float> @test_rootn_v2f32__y_1__strictfp(<2 x float> %x) #1 { ; CHECK-LABEL: define <2 x float> @test_rootn_v2f32__y_1__strictfp( ; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: ret <2 x float> [[X]] +; CHECK-NEXT: [[CALL:%.*]] = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> [[X]], <2 x i32> ) #[[ATTR0]] +; CHECK-NEXT: ret <2 x float> [[CALL]] ; entry: %call = tail call <2 x float> @_Z5rootnDv2_fDv2_i(<2 x float> %x, <2 x i32> ) #1 -- GitLab From 2a45f89aee8b05bb031c6e337df1524921de2e97 Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Fri, 12 Apr 2024 15:37:17 -0500 Subject: [PATCH 127/793] [ValueTracking] Add tests for `isKnowNonZero` of `X op (X != 0)`; NFC --- .../Transforms/InstSimplify/known-non-zero.ll | 211 ++++++++++++++++++ 1 file changed, 211 insertions(+) diff --git a/llvm/test/Transforms/InstSimplify/known-non-zero.ll b/llvm/test/Transforms/InstSimplify/known-non-zero.ll index fd2862eb04a2..f56fbb40a40d 100644 --- a/llvm/test/Transforms/InstSimplify/known-non-zero.ll +++ b/llvm/test/Transforms/InstSimplify/known-non-zero.ll @@ -400,3 +400,214 @@ define i1 @nonzero_reduce_or_fail(<2 x i8> %xx) { %r = icmp eq i8 %v, 0 ret i1 %r } + +define i1 @src_x_add_x_eq_0(i8 %x) { +; CHECK-LABEL: @src_x_add_x_eq_0( +; CHECK-NEXT: [[X_EQ_0:%.*]] = icmp eq i8 [[X:%.*]], 0 +; CHECK-NEXT: [[Y:%.*]] = zext i1 [[X_EQ_0]] to i8 +; CHECK-NEXT: [[V:%.*]] = add i8 [[X]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x_eq_0 = icmp eq i8 %x, 0 + %y = zext i1 %x_eq_0 to i8 + %v = add i8 %x, %y + %r = icmp eq i8 %v, 0 + ret i1 %r +} + +define i1 @src_x_add_x_eq_1_fail(i8 %x) { +; CHECK-LABEL: @src_x_add_x_eq_1_fail( +; CHECK-NEXT: [[X_EQ_1:%.*]] = icmp eq i8 [[X:%.*]], 1 +; CHECK-NEXT: [[Y:%.*]] = zext i1 [[X_EQ_1]] to i8 +; CHECK-NEXT: [[V:%.*]] = add i8 [[X]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x_eq_1 = icmp eq i8 %x, 1 + %y = zext i1 %x_eq_1 to i8 + %v = add i8 %x, %y + %r = icmp eq i8 %v, 0 + ret i1 %r +} + +define i1 @src_x_or_x_eq_0(i8 %x) { +; CHECK-LABEL: @src_x_or_x_eq_0( +; CHECK-NEXT: [[X_EQ_0:%.*]] = icmp eq i8 [[X:%.*]], 0 +; CHECK-NEXT: [[Y:%.*]] = sext i1 [[X_EQ_0]] to i8 +; CHECK-NEXT: [[V:%.*]] = or i8 [[X]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x_eq_0 = icmp eq i8 %x, 0 + %y = sext i1 %x_eq_0 to i8 + %v = or i8 %x, %y + %r = icmp eq i8 %v, 0 + ret i1 %r +} + +define i1 @src_x_or_x_sle_0_fail(i8 %x) { +; CHECK-LABEL: @src_x_or_x_sle_0_fail( +; CHECK-NEXT: [[X_EQ_0:%.*]] = icmp sle i8 [[X:%.*]], 0 +; CHECK-NEXT: [[Y:%.*]] = sext i1 [[X_EQ_0]] to i8 +; CHECK-NEXT: [[V:%.*]] = or i8 [[X]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x_eq_0 = icmp sle i8 %x, 0 + %y = sext i1 %x_eq_0 to i8 + %v = or i8 %x, %y + %r = icmp eq i8 %v, 0 + ret i1 %r +} + +define i1 @src_x_xor_x_eq_0(i8 %x) { +; CHECK-LABEL: @src_x_xor_x_eq_0( +; CHECK-NEXT: [[X_EQ_0:%.*]] = icmp eq i8 [[X:%.*]], 0 +; CHECK-NEXT: [[Y:%.*]] = zext i1 [[X_EQ_0]] to i8 +; CHECK-NEXT: [[V:%.*]] = xor i8 [[X]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x_eq_0 = icmp eq i8 %x, 0 + %y = zext i1 %x_eq_0 to i8 + %v = xor i8 %x, %y + %r = icmp eq i8 %v, 0 + ret i1 %r +} + +define i1 @src_x_xor_x_ne_0_fail(i8 %x) { +; CHECK-LABEL: @src_x_xor_x_ne_0_fail( +; CHECK-NEXT: [[X_NE_0:%.*]] = icmp ne i8 [[X:%.*]], 0 +; CHECK-NEXT: [[Y:%.*]] = zext i1 [[X_NE_0]] to i8 +; CHECK-NEXT: [[V:%.*]] = xor i8 [[X]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x_ne_0 = icmp ne i8 %x, 0 + %y = zext i1 %x_ne_0 to i8 + %v = xor i8 %x, %y + %r = icmp eq i8 %v, 0 + ret i1 %r +} + +define i1 @src_x_sub0_x_eq_0(i8 %x) { +; CHECK-LABEL: @src_x_sub0_x_eq_0( +; CHECK-NEXT: [[X_EQ_0:%.*]] = icmp eq i8 [[X:%.*]], 0 +; CHECK-NEXT: [[Y:%.*]] = sext i1 [[X_EQ_0]] to i8 +; CHECK-NEXT: [[V:%.*]] = sub i8 [[X]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x_eq_0 = icmp eq i8 %x, 0 + %y = sext i1 %x_eq_0 to i8 + %v = sub i8 %x, %y + %r = icmp eq i8 %v, 0 + ret i1 %r +} + +define i1 @src_x_sub0_z_eq_0_fail(i8 %x, i8 %z) { +; CHECK-LABEL: @src_x_sub0_z_eq_0_fail( +; CHECK-NEXT: [[Z_EQ_0:%.*]] = icmp eq i8 [[Z:%.*]], 0 +; CHECK-NEXT: [[Y:%.*]] = sext i1 [[Z_EQ_0]] to i8 +; CHECK-NEXT: [[V:%.*]] = sub i8 [[X:%.*]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %z_eq_0 = icmp eq i8 %z, 0 + %y = sext i1 %z_eq_0 to i8 + %v = sub i8 %x, %y + %r = icmp eq i8 %v, 0 + ret i1 %r +} + +define i1 @src_x_sub1_x_eq_0(i8 %x) { +; CHECK-LABEL: @src_x_sub1_x_eq_0( +; CHECK-NEXT: [[X_EQ_0:%.*]] = icmp eq i8 [[X:%.*]], 0 +; CHECK-NEXT: [[Y:%.*]] = zext i1 [[X_EQ_0]] to i8 +; CHECK-NEXT: [[V:%.*]] = sub i8 [[Y]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x_eq_0 = icmp eq i8 %x, 0 + %y = zext i1 %x_eq_0 to i8 + %v = sub i8 %y, %x + %r = icmp eq i8 %v, 0 + ret i1 %r +} + +define i1 @src_x_sub1_x_eq_0_or_fail(i8 %x, i1 %c1) { +; CHECK-LABEL: @src_x_sub1_x_eq_0_or_fail( +; CHECK-NEXT: [[X_EQ_0:%.*]] = icmp eq i8 [[X:%.*]], 0 +; CHECK-NEXT: [[X_EQ_0_OR:%.*]] = or i1 [[X_EQ_0]], [[C1:%.*]] +; CHECK-NEXT: [[Y:%.*]] = zext i1 [[X_EQ_0_OR]] to i8 +; CHECK-NEXT: [[V:%.*]] = sub i8 [[Y]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x_eq_0 = icmp eq i8 %x, 0 + %x_eq_0_or = or i1 %x_eq_0, %c1 + %y = zext i1 %x_eq_0_or to i8 + %v = sub i8 %y, %x + %r = icmp eq i8 %v, 0 + ret i1 %r +} + +define i1 @src_x_umax_x_eq_0(i8 %x) { +; CHECK-LABEL: @src_x_umax_x_eq_0( +; CHECK-NEXT: [[X_EQ_0:%.*]] = icmp eq i8 [[X:%.*]], 0 +; CHECK-NEXT: [[Y:%.*]] = sext i1 [[X_EQ_0]] to i8 +; CHECK-NEXT: [[V:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[X]]) +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x_eq_0 = icmp eq i8 %x, 0 + %y = sext i1 %x_eq_0 to i8 + %v = call i8 @llvm.umax.i8(i8 %y, i8 %x) + %r = icmp eq i8 %v, 0 + ret i1 %r +} + +define i1 @src_x_umax_x_ugt_10_fail(i8 %x) { +; CHECK-LABEL: @src_x_umax_x_ugt_10_fail( +; CHECK-NEXT: [[X_UGT_10:%.*]] = icmp ugt i8 [[X:%.*]], 10 +; CHECK-NEXT: [[Y:%.*]] = sext i1 [[X_UGT_10]] to i8 +; CHECK-NEXT: [[V:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[X]]) +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x_ugt_10 = icmp ugt i8 %x, 10 + %y = sext i1 %x_ugt_10 to i8 + %v = call i8 @llvm.umax.i8(i8 %y, i8 %x) + %r = icmp eq i8 %v, 0 + ret i1 %r +} + +define i1 @src_x_uadd.sat_x_eq_0(i8 %x) { +; CHECK-LABEL: @src_x_uadd.sat_x_eq_0( +; CHECK-NEXT: [[X_EQ_0:%.*]] = icmp eq i8 [[X:%.*]], 0 +; CHECK-NEXT: [[Y:%.*]] = zext i1 [[X_EQ_0]] to i8 +; CHECK-NEXT: [[V:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[Y]], i8 [[X]]) +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x_eq_0 = icmp eq i8 %x, 0 + %y = zext i1 %x_eq_0 to i8 + %v = call i8 @llvm.uadd.sat.i8(i8 %y, i8 %x) + %r = icmp eq i8 %v, 0 + ret i1 %r +} + +define i1 @src_x_uadd.sat_c1_fail(i8 %x, i1 %c1) { +; CHECK-LABEL: @src_x_uadd.sat_c1_fail( +; CHECK-NEXT: [[Y:%.*]] = zext i1 [[C1:%.*]] to i8 +; CHECK-NEXT: [[V:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[Y]], i8 [[X:%.*]]) +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %y = zext i1 %c1 to i8 + %v = call i8 @llvm.uadd.sat.i8(i8 %y, i8 %x) + %r = icmp eq i8 %v, 0 + ret i1 %r +} + -- GitLab From 223284316081e1af369c2d560da88e6211669250 Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Fri, 12 Apr 2024 15:55:52 -0500 Subject: [PATCH 128/793] [ValueTracking] Recognize `X op (X != 0)` as non-zero The ops supported are: `add`, `sub`, `xor`, `or`, `umax`, `uadd.sat` Proofs: https://alive2.llvm.org/ce/z/8ZMSRg The `add` case actually comes up in SPECInt, the rest are here mostly for completeness. Closes #88579 --- llvm/lib/Analysis/ValueTracking.cpp | 29 +++++++++++++ .../Transforms/InstSimplify/known-non-zero.ll | 42 ++++--------------- 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 063162ed38ba..3baa8ede28ff 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -2493,9 +2493,20 @@ static bool isNonZeroRecurrence(const PHINode *PN) { } } +static bool matchOpWithOpEqZero(Value *Op0, Value *Op1) { + ICmpInst::Predicate Pred; + return (match(Op0, m_ZExtOrSExt(m_ICmp(Pred, m_Specific(Op1), m_Zero()))) || + match(Op1, m_ZExtOrSExt(m_ICmp(Pred, m_Specific(Op0), m_Zero())))) && + Pred == ICmpInst::ICMP_EQ; +} + static bool isNonZeroAdd(const APInt &DemandedElts, unsigned Depth, const SimplifyQuery &Q, unsigned BitWidth, Value *X, Value *Y, bool NSW, bool NUW) { + // (X + (X != 0)) is non zero + if (matchOpWithOpEqZero(X, Y)) + return true; + if (NUW) return isKnownNonZero(Y, DemandedElts, Q, Depth) || isKnownNonZero(X, DemandedElts, Q, Depth); @@ -2539,6 +2550,11 @@ static bool isNonZeroAdd(const APInt &DemandedElts, unsigned Depth, static bool isNonZeroSub(const APInt &DemandedElts, unsigned Depth, const SimplifyQuery &Q, unsigned BitWidth, Value *X, Value *Y) { + // (X - (X != 0)) is non zero + // ((X != 0) - X) is non zero + if (matchOpWithOpEqZero(X, Y)) + return true; + // TODO: Move this case into isKnownNonEqual(). if (auto *C = dyn_cast(X)) if (C->isNullValue() && isKnownNonZero(Y, DemandedElts, Q, Depth)) @@ -2698,7 +2714,15 @@ static bool isKnownNonZeroFromOperator(const Operator *I, case Instruction::Sub: return isNonZeroSub(DemandedElts, Depth, Q, BitWidth, I->getOperand(0), I->getOperand(1)); + case Instruction::Xor: + // (X ^ (X != 0)) is non zero + if (matchOpWithOpEqZero(I->getOperand(0), I->getOperand(1))) + return true; + break; case Instruction::Or: + // (X | (X != 0)) is non zero + if (matchOpWithOpEqZero(I->getOperand(0), I->getOperand(1))) + return true; // X | Y != 0 if X != 0 or Y != 0. return isKnownNonZero(I->getOperand(1), DemandedElts, Q, Depth) || isKnownNonZero(I->getOperand(0), DemandedElts, Q, Depth); @@ -2989,6 +3013,11 @@ static bool isKnownNonZeroFromOperator(const Operator *I, return isKnownNonZero(II->getArgOperand(0), Q, Depth); case Intrinsic::umax: case Intrinsic::uadd_sat: + // umax(X, (X != 0)) is non zero + // X +usat (X != 0) is non zero + if (matchOpWithOpEqZero(II->getArgOperand(0), II->getArgOperand(1))) + return true; + return isKnownNonZero(II->getArgOperand(1), DemandedElts, Q, Depth) || isKnownNonZero(II->getArgOperand(0), DemandedElts, Q, Depth); case Intrinsic::smax: { diff --git a/llvm/test/Transforms/InstSimplify/known-non-zero.ll b/llvm/test/Transforms/InstSimplify/known-non-zero.ll index f56fbb40a40d..965c333d306d 100644 --- a/llvm/test/Transforms/InstSimplify/known-non-zero.ll +++ b/llvm/test/Transforms/InstSimplify/known-non-zero.ll @@ -403,11 +403,7 @@ define i1 @nonzero_reduce_or_fail(<2 x i8> %xx) { define i1 @src_x_add_x_eq_0(i8 %x) { ; CHECK-LABEL: @src_x_add_x_eq_0( -; CHECK-NEXT: [[X_EQ_0:%.*]] = icmp eq i8 [[X:%.*]], 0 -; CHECK-NEXT: [[Y:%.*]] = zext i1 [[X_EQ_0]] to i8 -; CHECK-NEXT: [[V:%.*]] = add i8 [[X]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %x_eq_0 = icmp eq i8 %x, 0 %y = zext i1 %x_eq_0 to i8 @@ -433,11 +429,7 @@ define i1 @src_x_add_x_eq_1_fail(i8 %x) { define i1 @src_x_or_x_eq_0(i8 %x) { ; CHECK-LABEL: @src_x_or_x_eq_0( -; CHECK-NEXT: [[X_EQ_0:%.*]] = icmp eq i8 [[X:%.*]], 0 -; CHECK-NEXT: [[Y:%.*]] = sext i1 [[X_EQ_0]] to i8 -; CHECK-NEXT: [[V:%.*]] = or i8 [[X]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %x_eq_0 = icmp eq i8 %x, 0 %y = sext i1 %x_eq_0 to i8 @@ -463,11 +455,7 @@ define i1 @src_x_or_x_sle_0_fail(i8 %x) { define i1 @src_x_xor_x_eq_0(i8 %x) { ; CHECK-LABEL: @src_x_xor_x_eq_0( -; CHECK-NEXT: [[X_EQ_0:%.*]] = icmp eq i8 [[X:%.*]], 0 -; CHECK-NEXT: [[Y:%.*]] = zext i1 [[X_EQ_0]] to i8 -; CHECK-NEXT: [[V:%.*]] = xor i8 [[X]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %x_eq_0 = icmp eq i8 %x, 0 %y = zext i1 %x_eq_0 to i8 @@ -493,11 +481,7 @@ define i1 @src_x_xor_x_ne_0_fail(i8 %x) { define i1 @src_x_sub0_x_eq_0(i8 %x) { ; CHECK-LABEL: @src_x_sub0_x_eq_0( -; CHECK-NEXT: [[X_EQ_0:%.*]] = icmp eq i8 [[X:%.*]], 0 -; CHECK-NEXT: [[Y:%.*]] = sext i1 [[X_EQ_0]] to i8 -; CHECK-NEXT: [[V:%.*]] = sub i8 [[X]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %x_eq_0 = icmp eq i8 %x, 0 %y = sext i1 %x_eq_0 to i8 @@ -523,11 +507,7 @@ define i1 @src_x_sub0_z_eq_0_fail(i8 %x, i8 %z) { define i1 @src_x_sub1_x_eq_0(i8 %x) { ; CHECK-LABEL: @src_x_sub1_x_eq_0( -; CHECK-NEXT: [[X_EQ_0:%.*]] = icmp eq i8 [[X:%.*]], 0 -; CHECK-NEXT: [[Y:%.*]] = zext i1 [[X_EQ_0]] to i8 -; CHECK-NEXT: [[V:%.*]] = sub i8 [[Y]], [[X]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %x_eq_0 = icmp eq i8 %x, 0 %y = zext i1 %x_eq_0 to i8 @@ -555,11 +535,7 @@ define i1 @src_x_sub1_x_eq_0_or_fail(i8 %x, i1 %c1) { define i1 @src_x_umax_x_eq_0(i8 %x) { ; CHECK-LABEL: @src_x_umax_x_eq_0( -; CHECK-NEXT: [[X_EQ_0:%.*]] = icmp eq i8 [[X:%.*]], 0 -; CHECK-NEXT: [[Y:%.*]] = sext i1 [[X_EQ_0]] to i8 -; CHECK-NEXT: [[V:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[X]]) -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %x_eq_0 = icmp eq i8 %x, 0 %y = sext i1 %x_eq_0 to i8 @@ -585,11 +561,7 @@ define i1 @src_x_umax_x_ugt_10_fail(i8 %x) { define i1 @src_x_uadd.sat_x_eq_0(i8 %x) { ; CHECK-LABEL: @src_x_uadd.sat_x_eq_0( -; CHECK-NEXT: [[X_EQ_0:%.*]] = icmp eq i8 [[X:%.*]], 0 -; CHECK-NEXT: [[Y:%.*]] = zext i1 [[X_EQ_0]] to i8 -; CHECK-NEXT: [[V:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[Y]], i8 [[X]]) -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %x_eq_0 = icmp eq i8 %x, 0 %y = zext i1 %x_eq_0 to i8 -- GitLab From 250c39cd7aae8d4a6a76e2f04cfe5ce657f8260c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 20 May 2024 23:30:51 +0300 Subject: [PATCH 129/793] [libcxx] Add cast to avoid pointer casting warning on Windows (#92738) This avoids the following build time warning, when building with the latest nightly Clang: warning: cast from 'FARPROC' (aka 'int (*)() __attribute__((stdcall))') to 'GetSystemTimeAsFileTimePtr' (aka 'void (*)(_FILETIME *) __attribute__((stdcall))') converts to incompatible function type [-Wcast-function-type-mismatch] This warning seems to have appeared since Clang commit 999d4f840777bf8de26d45947192aa0728edc0fb, which restructured. The GetProcAddress function returns a `FARPROC` type, which is `int (WINAPI *)()`. Directly casting this to another function pointer type triggers this warning, but casting to a `void*` inbetween avoids this issue. (On Unix-like platforms, dlsym returns a `void*`, which doesn't exhibit this casting problem.) --- libcxx/src/chrono.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcxx/src/chrono.cpp b/libcxx/src/chrono.cpp index e7d6dfbc2292..83e8a64504ae 100644 --- a/libcxx/src/chrono.cpp +++ b/libcxx/src/chrono.cpp @@ -77,8 +77,8 @@ typedef void(WINAPI* GetSystemTimeAsFileTimePtr)(LPFILETIME); class GetSystemTimeInit { public: GetSystemTimeInit() { - fp = - (GetSystemTimeAsFileTimePtr)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetSystemTimePreciseAsFileTime"); + fp = (GetSystemTimeAsFileTimePtr)(void*)GetProcAddress( + GetModuleHandleW(L"kernel32.dll"), "GetSystemTimePreciseAsFileTime"); if (fp == nullptr) fp = GetSystemTimeAsFileTime; } -- GitLab From 1f07bfb92c2a62731a5ae3ec2d135e3869634c01 Mon Sep 17 00:00:00 2001 From: Spenser Bauman Date: Mon, 20 May 2024 16:36:45 -0400 Subject: [PATCH 130/793] [mlir][tensor] Implement folding logic for size 0 tensor and memref ops (#90814) Implement folding and rewrite logic to eliminate no-op tensor and memref operations. This handles two specific cases: 1. tensor.insert_slice operations where the size of the inserted slice is known to be 0. 2. memref.copy operations where either the source or target memrefs are known to be emtpy. Co-authored-by: Spenser Bauman --- mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp | 22 +++++++++++++++++++++- mlir/lib/Dialect/Tensor/IR/TensorOps.cpp | 3 +++ mlir/test/Dialect/MemRef/canonicalize.mlir | 10 ++++++++++ mlir/test/Dialect/Tensor/canonicalize.mlir | 12 ++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp index 45f39c80041c..d70e6d0b79cd 100644 --- a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp +++ b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp @@ -833,11 +833,31 @@ struct FoldSelfCopy : public OpRewritePattern { return success(); } }; + +struct FoldEmptyCopy final : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + static bool isEmptyMemRef(BaseMemRefType type) { + return type.hasRank() && + llvm::any_of(type.getShape(), [](int64_t x) { return x == 0; }); + } + + LogicalResult matchAndRewrite(CopyOp copyOp, + PatternRewriter &rewriter) const override { + if (isEmptyMemRef(copyOp.getSource().getType()) || + isEmptyMemRef(copyOp.getTarget().getType())) { + rewriter.eraseOp(copyOp); + return success(); + } + + return failure(); + } +}; } // namespace void CopyOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { - results.add(context); + results.add(context); } LogicalResult CopyOp::fold(FoldAdaptor adaptor, diff --git a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp index 8a6df82abb31..8545c7b9af8f 100644 --- a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp +++ b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp @@ -2609,6 +2609,9 @@ OpFoldResult InsertSliceOp::fold(FoldAdaptor) { return getResult(); if (auto result = foldInsertAfterExtractSlice(*this)) return result; + if (llvm::any_of(getMixedSizes(), + [](OpFoldResult ofr) { return isConstantIntValue(ofr, 0); })) + return getDest(); return OpFoldResult(); } diff --git a/mlir/test/Dialect/MemRef/canonicalize.mlir b/mlir/test/Dialect/MemRef/canonicalize.mlir index f442a61dc31e..c4ff6480a4ce 100644 --- a/mlir/test/Dialect/MemRef/canonicalize.mlir +++ b/mlir/test/Dialect/MemRef/canonicalize.mlir @@ -692,6 +692,16 @@ func.func @self_copy(%m1: memref) { // ----- +// CHECK-LABEL: func @empty_copy +// CHECK-NEXT: return +func.func @empty_copy(%m1: memref<0x10xf32>, %m2: memref) { + memref.copy %m1, %m2 : memref<0x10xf32> to memref + memref.copy %m2, %m1 : memref to memref<0x10xf32> + return +} + +// ----- + func.func @scopeMerge() { memref.alloca_scope { %cnt = "test.count"() : () -> index diff --git a/mlir/test/Dialect/Tensor/canonicalize.mlir b/mlir/test/Dialect/Tensor/canonicalize.mlir index b5a82eb3e903..914e5e8b8c4b 100644 --- a/mlir/test/Dialect/Tensor/canonicalize.mlir +++ b/mlir/test/Dialect/Tensor/canonicalize.mlir @@ -542,6 +542,18 @@ func.func @trivial_insert_slice(%arg0 : tensor<4x6x16x32xi8>, %arg1 : tensor<4x6 // ----- +// CHECK-LABEL: func @empty_insert_slice +// CHECK-SAME: %[[ARG0:.[a-z0-9A-Z_]+]]: tensor<0x2xi8> +// CHECK-SAME: %[[ARG1:.[a-z0-9A-Z_]+]]: tensor<3x3xi8> +// CHECK-NOT: tensor.extract_slice +// CHECK: return %[[ARG1]] : tensor<3x3xi8> +func.func @empty_insert_slice(%arg0 : tensor<0x2xi8>, %arg1 : tensor<3x3xi8>) -> tensor<3x3xi8> { + %0 = tensor.insert_slice %arg0 into %arg1[0, 0] [0, 2] [1, 1] : tensor<0x2xi8> into tensor<3x3xi8> + return %0 : tensor<3x3xi8> +} + +// ----- + // CHECK-LABEL: func @rank_reducing_tensor_of_cast // CHECK-SAME: %[[ARG0:.[a-z0-9A-Z_]+]]: tensor<4x6x16x32xi8> // CHECK: %[[S:.+]] = tensor.extract_slice %arg0[0, 1, 0, 0] [1, 1, 16, 32] [1, 1, 1, 1] : tensor<4x6x16x32xi8> to tensor<16x32xi8> -- GitLab From 753f7e814514ddb2bb2fd837549d5958cf0ef343 Mon Sep 17 00:00:00 2001 From: Changpeng Fang Date: Mon, 20 May 2024 13:37:01 -0700 Subject: [PATCH 131/793] [OpenCL] Fix an infinite loop in builidng AddrSpaceQualType (#92612) In building AddrSpaceQualType (https://github.com/llvm/llvm-project/pull/90048), there is a bug in removeAddrSpaceQualType() for arrays. Arrays are weird because qualifiers on the element type also count as qualifiers on the type, so getSingleStepDesugaredType() can't remove the sugar on arrays. This results in an infinite loop in removeAddrSpaceQualType. To fix the issue, we use ASTContext::getUnqualifiedArrayType instead, which strips the qualifier off the element type, then reconstruct the array type. --- clang/include/clang/AST/ASTContext.h | 2 +- clang/lib/AST/ASTContext.cpp | 32 +++++++++++-------- .../array-type-infinite-loop.clcpp | 25 +++++++++++++++ 3 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 clang/test/CodeGenOpenCLCXX/array-type-infinite-loop.clcpp diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index e03b11219478..2ce2b810d363 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2611,7 +2611,7 @@ public: /// /// \returns if this is an array type, the completely unqualified array type /// that corresponds to it. Otherwise, returns T.getUnqualifiedType(). - QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals); + QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals) const; /// Determine whether the given types are equivalent after /// cvr-qualifiers have been removed. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 8fc2bb8c401c..52eab5feb062 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3054,21 +3054,27 @@ QualType ASTContext::removeAddrSpaceQualType(QualType T) const { if (!T.hasAddressSpace()) return T; - // If we are composing extended qualifiers together, merge together - // into one ExtQuals node. QualifierCollector Quals; const Type *TypeNode; + // For arrays, strip the qualifier off the element type, then reconstruct the + // array type + if (T.getTypePtr()->isArrayType()) { + T = getUnqualifiedArrayType(T, Quals); + TypeNode = T.getTypePtr(); + } else { + // If we are composing extended qualifiers together, merge together + // into one ExtQuals node. + while (T.hasAddressSpace()) { + TypeNode = Quals.strip(T); + + // If the type no longer has an address space after stripping qualifiers, + // jump out. + if (!QualType(TypeNode, 0).hasAddressSpace()) + break; - while (T.hasAddressSpace()) { - TypeNode = Quals.strip(T); - - // If the type no longer has an address space after stripping qualifiers, - // jump out. - if (!QualType(TypeNode, 0).hasAddressSpace()) - break; - - // There might be sugar in the way. Strip it and try again. - T = T.getSingleStepDesugaredType(*this); + // There might be sugar in the way. Strip it and try again. + T = T.getSingleStepDesugaredType(*this); + } } Quals.removeAddressSpace(); @@ -6093,7 +6099,7 @@ CanQualType ASTContext::getCanonicalParamType(QualType T) const { } QualType ASTContext::getUnqualifiedArrayType(QualType type, - Qualifiers &quals) { + Qualifiers &quals) const { SplitQualType splitType = type.getSplitUnqualifiedType(); // FIXME: getSplitUnqualifiedType() actually walks all the way to diff --git a/clang/test/CodeGenOpenCLCXX/array-type-infinite-loop.clcpp b/clang/test/CodeGenOpenCLCXX/array-type-infinite-loop.clcpp new file mode 100644 index 000000000000..db9d7eb3281f --- /dev/null +++ b/clang/test/CodeGenOpenCLCXX/array-type-infinite-loop.clcpp @@ -0,0 +1,25 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +//RUN: %clang_cc1 %s -triple spir -emit-llvm -O1 -o - | FileCheck %s + +// CHECK-LABEL: define dso_local spir_kernel void @test( +// CHECK-SAME: ptr addrspace(1) nocapture noundef readonly align 8 [[IN:%.*]], ptr addrspace(1) nocapture noundef writeonly align 8 [[OUT:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] !kernel_arg_addr_space [[META3:![0-9]+]] !kernel_arg_access_qual [[META4:![0-9]+]] !kernel_arg_type [[META5:![0-9]+]] !kernel_arg_base_type [[META5]] !kernel_arg_type_qual [[META6:![0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[IN]], i32 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr addrspace(1) [[ARRAYIDX1]], align 8, !tbaa [[TBAA7:![0-9]+]] +// CHECK-NEXT: store i64 [[TMP0]], ptr addrspace(1) [[OUT]], align 8, !tbaa [[TBAA7]] +// CHECK-NEXT: ret void +// +__kernel void test(__global long *In, __global long *Out) { + long m[4] = { In[0], In[1], 0, 0 }; + *Out = m[1]; +} +//. +// CHECK: [[META3]] = !{i32 1, i32 1} +// CHECK: [[META4]] = !{!"none", !"none"} +// CHECK: [[META5]] = !{!"long*", !"long*"} +// CHECK: [[META6]] = !{!"", !""} +// CHECK: [[TBAA7]] = !{[[META8:![0-9]+]], [[META8]], i64 0} +// CHECK: [[META8]] = !{!"long", [[META9:![0-9]+]], i64 0} +// CHECK: [[META9]] = !{!"omnipotent char", [[META10:![0-9]+]], i64 0} +// CHECK: [[META10]] = !{!"Simple C++ TBAA"} +//. -- GitLab From 51ba7a816ccdadf7f943fb30a1933ded72a4c178 Mon Sep 17 00:00:00 2001 From: "Nick Desaulniers (paternity leave)" Date: Mon, 20 May 2024 14:05:49 -0700 Subject: [PATCH 132/793] [libc][setjmp] disable -ftrivial-auto-var-init=pattern for now (#92796) This would consistently fail for me locally, to the point where I could not run ninja libc-unit-tests without ninja libc_setjmp_unittests failing. Turns out that since I enabled -ftrivial-auto-var-init=pattern in commit 1d5c16d ("[libc] default enable -ftrivial-auto-var-init=pattern (#78776)") this has been a problem. Our x86_64 setjmp definition disabled -Wuninitialized, so we wound up clobbering these registers and instead backing up 0xAAAAAAAAAAAAAAAA rather than the actual register value. The implemenation should be rewritten entirely. I've proposed three different ways to do so (linked below). Until we decide which way to go, at least disable this hardening feature for this function for now so that the unit tests go back to green. Link: #87837 Link: #88054 Link: #88157 Fixes: #91164 --- libc/src/setjmp/x86_64/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libc/src/setjmp/x86_64/CMakeLists.txt b/libc/src/setjmp/x86_64/CMakeLists.txt index 9899c00e7c4a..ae84322a6540 100644 --- a/libc/src/setjmp/x86_64/CMakeLists.txt +++ b/libc/src/setjmp/x86_64/CMakeLists.txt @@ -9,6 +9,11 @@ add_entrypoint_object( COMPILE_OPTIONS -O3 -fno-omit-frame-pointer + # TODO: Remove once one of these lands: + # https://github.com/llvm/llvm-project/pull/87837 + # https://github.com/llvm/llvm-project/pull/88054 + # https://github.com/llvm/llvm-project/pull/88157 + -ftrivial-auto-var-init=uninitialized ) add_entrypoint_object( -- GitLab From dce197ac9219319e5ea76a110100e87e225684d8 Mon Sep 17 00:00:00 2001 From: "Nick Desaulniers (paternity leave)" Date: Mon, 20 May 2024 14:15:24 -0700 Subject: [PATCH 133/793] [libc][errno] remove mips+sparc specific errnos (#92798) These are untested and unsupported platforms. The pattern used makes sense for platform specific error numbers, but these are platforms we do not support. Excise this code. Link: #91150 --- .../llvm-libc-macros/linux/CMakeLists.txt | 6 ----- .../linux/error-number-macros.h | 8 ------- .../linux/mips/CMakeLists.txt | 5 ---- .../linux/mips/error-number-macros.h | 24 ------------------- .../linux/sparc/CMakeLists.txt | 5 ---- .../linux/sparc/error-number-macros.h | 24 ------------------- 6 files changed, 72 deletions(-) delete mode 100644 libc/include/llvm-libc-macros/linux/mips/CMakeLists.txt delete mode 100644 libc/include/llvm-libc-macros/linux/mips/error-number-macros.h delete mode 100644 libc/include/llvm-libc-macros/linux/sparc/CMakeLists.txt delete mode 100644 libc/include/llvm-libc-macros/linux/sparc/error-number-macros.h diff --git a/libc/include/llvm-libc-macros/linux/CMakeLists.txt b/libc/include/llvm-libc-macros/linux/CMakeLists.txt index a07803103eef..461b190c02ea 100644 --- a/libc/include/llvm-libc-macros/linux/CMakeLists.txt +++ b/libc/include/llvm-libc-macros/linux/CMakeLists.txt @@ -1,13 +1,7 @@ -add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/mips) -add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/sparc) - add_header( error_number_macros HDR error-number-macros.h - DEPENDS - .mips.error_number_macros - .sparc.error_number_macros ) add_header( diff --git a/libc/include/llvm-libc-macros/linux/error-number-macros.h b/libc/include/llvm-libc-macros/linux/error-number-macros.h index 4c8b3feb3dc3..1643a70918da 100644 --- a/libc/include/llvm-libc-macros/linux/error-number-macros.h +++ b/libc/include/llvm-libc-macros/linux/error-number-macros.h @@ -1,13 +1,6 @@ #ifndef LLVM_LIBC_MACROS_LINUX_ERROR_NUMBER_MACROS_H #define LLVM_LIBC_MACROS_LINUX_ERROR_NUMBER_MACROS_H -#if defined(__mips__) -#include "mips/error-number-macros.h" - -#elif defined(__sparc__) -#include "sparc/error-number-macros.h" - -#else #ifndef ECANCELED #define ECANCELED 125 #endif // ECANCELED @@ -27,6 +20,5 @@ #ifndef EHWPOISON #define EHWPOISON 133 #endif // EHWPOISON -#endif #endif // LLVM_LIBC_MACROS_LINUX_ERROR_NUMBER_MACROS_H diff --git a/libc/include/llvm-libc-macros/linux/mips/CMakeLists.txt b/libc/include/llvm-libc-macros/linux/mips/CMakeLists.txt deleted file mode 100644 index eee4cfd19396..000000000000 --- a/libc/include/llvm-libc-macros/linux/mips/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -add_header( - error_number_macros - HDR - error-number-macros.h -) diff --git a/libc/include/llvm-libc-macros/linux/mips/error-number-macros.h b/libc/include/llvm-libc-macros/linux/mips/error-number-macros.h deleted file mode 100644 index af2a4243e3ce..000000000000 --- a/libc/include/llvm-libc-macros/linux/mips/error-number-macros.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef LLVM_LIBC_MACROS_LINUX_MIPS_ERROR_NUMBER_MACROS_H -#define LLVM_LIBC_MACROS_LINUX_MIPS_ERROR_NUMBER_MACROS_H - -#ifndef ECANCELED -#define ECANCELED 158 -#endif // ECANCELED - -#ifndef EOWNERDEAD -#define EOWNERDEAD 165 -#endif // EOWNERDEAD - -#ifndef ENOTRECOVERABLE -#define ENOTRECOVERABLE 166 -#endif // ENOTRECOVERABLE - -#ifndef ERFKILL -#define ERFKILL 167 -#endif // ERFKILL - -#ifndef EHWPOISON -#define EHWPOISON 168 -#endif // EHWPOISON - -#endif // LLVM_LIBC_MACROS_LINUX_MIPS_ERROR_NUMBER_MACROS_H diff --git a/libc/include/llvm-libc-macros/linux/sparc/CMakeLists.txt b/libc/include/llvm-libc-macros/linux/sparc/CMakeLists.txt deleted file mode 100644 index eee4cfd19396..000000000000 --- a/libc/include/llvm-libc-macros/linux/sparc/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -add_header( - error_number_macros - HDR - error-number-macros.h -) diff --git a/libc/include/llvm-libc-macros/linux/sparc/error-number-macros.h b/libc/include/llvm-libc-macros/linux/sparc/error-number-macros.h deleted file mode 100644 index 76a1408bf760..000000000000 --- a/libc/include/llvm-libc-macros/linux/sparc/error-number-macros.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef LLVM_LIBC_MACROS_LINUX_SPARC_ERROR_NUMBER_MACROS_H -#define LLVM_LIBC_MACROS_LINUX_SPARC_ERROR_NUMBER_MACROS_H - -#ifndef ECANCELED -#define ECANCELED 127 -#endif // ECANCELED - -#ifndef EOWNERDEAD -#define EOWNERDEAD 132 -#endif // EOWNERDEAD - -#ifndef ENOTRECOVERABLE -#define ENOTRECOVERABLE 133 -#endif // ENOTRECOVERABLE - -#ifndef ERFKILL -#define ERFKILL 134 -#endif // ERFKILL - -#ifndef EHWPOISON -#define EHWPOISON 135 -#endif // EHWPOISON - -#endif // LLVM_LIBC_MACROS_LINUX_SPARC_ERROR_NUMBER_MACROS_H -- GitLab From 7ecdf620330d8e044a48b6f59f8eddd2f88f01d4 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Mon, 20 May 2024 14:51:17 -0700 Subject: [PATCH 134/793] [MCA] use std::function instead of function_ref when storing (#91039) This patch changes uses of llvm::function_ref for std::function when storing the callback inside of a class. The LLVM Programmer's manual mentions that llvm::function_ref is not safe to store as it contains pointers to external memory that are not guaranteed to exist in the future when it is stored. This causes issues when setting callbacks inside of a class that manages MCA state. Passing a lambda directly to the set callback functions will end up causing UB/segfaults when the lambda is called as some external memory is now invalid. This is easy to work around (create a separate std::function, pass that into the function setting the callback), but isn't ideal. --- llvm/include/llvm/MCA/IncrementalSourceMgr.h | 2 +- llvm/include/llvm/MCA/InstrBuilder.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/MCA/IncrementalSourceMgr.h b/llvm/include/llvm/MCA/IncrementalSourceMgr.h index d53f1138b940..81f9b51cf42f 100644 --- a/llvm/include/llvm/MCA/IncrementalSourceMgr.h +++ b/llvm/include/llvm/MCA/IncrementalSourceMgr.h @@ -41,7 +41,7 @@ class IncrementalSourceMgr : public SourceMgr { bool EOS = false; /// Called when an instruction is no longer needed. - using InstFreedCallback = llvm::function_ref; + using InstFreedCallback = std::function; InstFreedCallback InstFreedCB; public: diff --git a/llvm/include/llvm/MCA/InstrBuilder.h b/llvm/include/llvm/MCA/InstrBuilder.h index c8619af04b33..359437248914 100644 --- a/llvm/include/llvm/MCA/InstrBuilder.h +++ b/llvm/include/llvm/MCA/InstrBuilder.h @@ -79,8 +79,7 @@ class InstrBuilder { bool FirstCallInst; bool FirstReturnInst; - using InstRecycleCallback = - llvm::function_ref; + using InstRecycleCallback = std::function; InstRecycleCallback InstRecycleCB; Expected -- GitLab From 33b7833891dcacf9e81e911ed59932fd55113fff Mon Sep 17 00:00:00 2001 From: Javed Absar <106147771+javedabsar1@users.noreply.github.com> Date: Mon, 20 May 2024 23:10:51 +0100 Subject: [PATCH 135/793] [MLIR][Linalg] Add more specialize patterns (#91153) Currently only linalg.copy is recognized when trying to specialize linalg.generics back to named op. This diff enables recognition of more generic to named op e.g. linalg.fill, elemwise unary/binary. --- .../mlir/Dialect/Linalg/IR/LinalgInterfaces.h | 16 ++++ .../Dialect/Linalg/IR/LinalgInterfaces.cpp | 93 +++++++++++++++++++ .../Dialect/Linalg/Transforms/Specialize.cpp | 72 ++++++++++++++ .../Linalg/transform-op-specialize.mlir | 25 +++++ ...ansform-op-specialize_elemwise_binary.mlir | 76 +++++++++++++++ ...ransform-op-specialize_elemwise_unary.mlir | 25 +++++ 6 files changed, 307 insertions(+) create mode 100644 mlir/test/Dialect/Linalg/transform-op-specialize_elemwise_binary.mlir create mode 100644 mlir/test/Dialect/Linalg/transform-op-specialize_elemwise_unary.mlir diff --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgInterfaces.h b/mlir/include/mlir/Dialect/Linalg/IR/LinalgInterfaces.h index f92843a1dcb9..08afdf373f01 100644 --- a/mlir/include/mlir/Dialect/Linalg/IR/LinalgInterfaces.h +++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgInterfaces.h @@ -28,6 +28,7 @@ namespace mlir { namespace linalg { class IteratorTypeAttr; class LinalgOp; +class GenericOp; namespace detail { /// Implementation of the method that check if given operands @@ -115,6 +116,21 @@ bool isaConvolutionOpInterface(LinalgOp linalgOp); /// Checks whether `linalgOp` is semantically equivalent to a `linalg.copyOp`. bool isaCopyOpInterface(LinalgOp linalgOp); +/// Checks whether a given `genericOp` is semantically equivalent to a single +/// linalgelementwise unary op. e.g. linalg.exp. +/// A linalg.generic body could be a series of unary elementwise ops e.g. +/// `exp(neg(x))`, such as formed by linalg op fusion. Here we restrict it to +/// detecting cases where body is is a single computation op. +bool isaElemwiseSingleUnaryOpInterface(GenericOp genericOp); + +/// Checks whether `genericOp` is semantically equivalent to a single linalg +/// elementwise binary op e.g. linalg.sub. +bool isaElemwiseSingleBinaryOpInterface(GenericOp genericOp); + +/// Checks whether `genericOp` is semantically equivalent to a `linalg.fill`. +/// Returns the scalar fill value if true. +std::optional isaFillOpInterface(GenericOp genericOp); + namespace detail { /// Returns true if the block contains a contraction of the following form: diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp index 3627ff6617ed..f35ab3b856b4 100644 --- a/mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp +++ b/mlir/lib/Dialect/Linalg/IR/LinalgInterfaces.cpp @@ -70,6 +70,99 @@ bool linalg::isaCopyOpInterface(LinalgOp linalgOp) { return llvm::hasSingleElement(linalgOp.getBlock()->getOperations()); } +//===----------------------------------------------------------------------===// +// FillOpInterface implementation +//===----------------------------------------------------------------------===// +std::optional linalg::isaFillOpInterface(GenericOp genericOp) { + // Structural. + if (genericOp.getNumParallelLoops() != genericOp.getNumLoops() || + genericOp.getNumDpsInputs() != 1 || genericOp.getNumDpsInits() != 1) + return std::nullopt; + + // Input should be referenced and init should not. + if (!genericOp.payloadUsesValueFromOperand(genericOp.getDpsInputOperand(0)) || + genericOp.payloadUsesValueFromOperand(genericOp.getDpsInitOperand(0))) + return std::nullopt; + + OpOperand *value = genericOp.getDpsInputOperand(0); + if (!genericOp.isScalar(value)) + return std::nullopt; + + Block *body = genericOp.getBody(); + if (body->getOperations().size() != 1) + return std::nullopt; + + auto yieldOp = dyn_cast(body->back()); + if (!yieldOp || yieldOp.getNumOperands() != 1 || + yieldOp->getOperand(0) != body->getArgument(0)) + return std::nullopt; + return value->get(); +} + +//===----------------------------------------------------------------------===// +// Elementwise Single Unary/Binary-OpInterface implementation +//===----------------------------------------------------------------------===// +static bool +isaElemwiseSingleUnaryOrBinaryOpInterface(linalg::GenericOp genericOp, + unsigned arity) { + // Check all loops are parallel, and have only tensor semantics. + if (genericOp.getNumParallelLoops() != genericOp.getNumLoops() || + genericOp.getNumLoops() < 1 || !genericOp.hasPureTensorSemantics()) + return false; + + // Check there are arity-inputs, 1-output and all are identity-maps. + if (genericOp.getNumDpsInputs() != arity || genericOp.getNumDpsInits() != 1 || + !llvm::all_of(genericOp.getIndexingMapsArray(), + [](AffineMap map) { return map.isIdentity(); })) + return false; + + // Init should not be referenced for elementwise operations. + if (genericOp.payloadUsesValueFromOperand(genericOp.getDpsInitOperand(0))) + return false; + + // A linalg.generic could be series of elementwise ops e.g. exp(neg(x)) such + // as resulting from producer-consumer fusion. Here, we restrict to two ops in + // the body, where the first is the elementwise single op and the second a + // yield. + Block *body = genericOp.getBody(); + if (body->getOperations().size() != 2) + return false; + + Operation *op = &body->front(); + if (op->getNumOperands() != arity || op->getNumResults() != 1) + return false; + + auto yieldOp = dyn_cast(body->back()); + if (!yieldOp || yieldOp.getNumOperands() != 1 || + yieldOp->getOperand(0).getDefiningOp() != op) + return false; + return true; +} + +bool linalg::isaElemwiseSingleUnaryOpInterface(linalg::GenericOp genericOp) { + // All basic elemwise checks. + if (!isaElemwiseSingleUnaryOrBinaryOpInterface(genericOp, 1)) + return false; + + // Check input is actully used. + if (!genericOp.payloadUsesValueFromOperand(genericOp.getDpsInputOperand(0))) + return false; + return true; +} + +bool linalg::isaElemwiseSingleBinaryOpInterface(linalg::GenericOp genericOp) { + if (!isaElemwiseSingleUnaryOrBinaryOpInterface(genericOp, 2)) + return false; + + // Check both inputs are used (elementwise). + OpOperand *inputOpOperand0 = genericOp.getDpsInputOperand(0); + OpOperand *inputOpOperand1 = genericOp.getDpsInputOperand(1); + if (!genericOp.payloadUsesValueFromOperand(inputOpOperand0) || + !genericOp.payloadUsesValueFromOperand(inputOpOperand1)) + return false; + return true; +} + //===----------------------------------------------------------------------===// // ContractionOpInterface implementation //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/Linalg/Transforms/Specialize.cpp b/mlir/lib/Dialect/Linalg/Transforms/Specialize.cpp index 4c437b5db2c7..2bc4d7fbfadc 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/Specialize.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/Specialize.cpp @@ -14,13 +14,50 @@ #include "mlir/Dialect/Linalg/IR/Linalg.h" #include "mlir/Dialect/Linalg/IR/LinalgInterfaces.h" #include "mlir/Dialect/Linalg/Transforms/Transforms.h" +#include "mlir/Dialect/Math/IR/Math.h" #include "llvm/Support/Debug.h" #define DEBUG_TYPE "linalg-specialization" +#define REPLACE_BINARY_OP(NEWOP, OPERANDS_SWAP) \ + (rewriter.replaceOpWithNewOp( \ + genericOp, \ + ValueRange{genericOp.getDpsInputs()[(OPERANDS_SWAP) ? 1 : 0], \ + genericOp.getDpsInputs()[(OPERANDS_SWAP) ? 0 : 1]}, \ + ValueRange{genericOp.getDpsInits()[0]})) + +#define REPLACE_UNARY_OP(NEWOP) \ + (rewriter.replaceOpWithNewOp(genericOp, \ + ValueRange{genericOp.getDpsInputs()[0]}, \ + ValueRange{genericOp.getDpsInits()[0]})) + using namespace mlir; using namespace mlir::linalg; +// Given a elementwise single binary linalg generic op, checks whether the +// binary op accesses operands as swapped. e.g. +// this differentiates between a linalg-generic body that contains: +// ^bb0(%a: f32, %b: f32, %c : f32): +// %0 = arith.subf %a, %b : f32 +// linalg.yield %0: f32 +// against: +// ^bb0(%a: f32, %b: f32, %c : f32): +// %0 = arith.subf %b, %a : f32 +// linalg.yield %0: f32 +// Former is linalg.sub(a,b), latter is linalg.sub(b,a). +static bool areBinOpsSwapped(GenericOp genericOp) { + Block *body = genericOp.getBody(); + Operation *op = &body->front(); + bool swapped = false; + if (op->getOpOperand(0).get() != body->getArgument(0)) { + swapped = true; + assert(op->getOpOperand(0).get() == body->getArgument(1) && + op->getOpOperand(1).get() == body->getArgument(0) && + "binary op uses just one block arg"); + } + return swapped; +} + FailureOr mlir::linalg::specializeGenericOp(RewriterBase &rewriter, GenericOp genericOp) { if (isaCopyOpInterface(genericOp)) { @@ -28,5 +65,40 @@ FailureOr mlir::linalg::specializeGenericOp(RewriterBase &rewriter, genericOp, genericOp.getDpsInputs()[0], genericOp.getDpsInits()[0]); return namedOp; } + + if (isaFillOpInterface(genericOp)) { + LinalgOp namedOp = rewriter.replaceOpWithNewOp( + genericOp, genericOp.getDpsInputs()[0], genericOp.getDpsInits()[0]); + return namedOp; + } + + if (isaElemwiseSingleUnaryOpInterface(genericOp)) { + Operation *op = &genericOp.getBody()->front(); + if (isa(op)) { + LinalgOp namedOp = REPLACE_UNARY_OP(ExpOp); + return namedOp; + } + } + + if (isaElemwiseSingleBinaryOpInterface(genericOp)) { + bool swap = areBinOpsSwapped(genericOp); + Operation *op = &genericOp.getBody()->front(); + if (isa(op)) { + LinalgOp namedOp = REPLACE_BINARY_OP(AddOp, swap); + return namedOp; + } + if (isa(op)) { + LinalgOp namedOp = REPLACE_BINARY_OP(SubOp, swap); + return namedOp; + } + if (isa(op)) { + LinalgOp namedOp = REPLACE_BINARY_OP(MulOp, swap); + return namedOp; + } + if (isa(op)) { + LinalgOp namedOp = REPLACE_BINARY_OP(DivOp, swap); + return namedOp; + } + } return failure(); } diff --git a/mlir/test/Dialect/Linalg/transform-op-specialize.mlir b/mlir/test/Dialect/Linalg/transform-op-specialize.mlir index 8a22c115f311..35679db7412f 100644 --- a/mlir/test/Dialect/Linalg/transform-op-specialize.mlir +++ b/mlir/test/Dialect/Linalg/transform-op-specialize.mlir @@ -141,3 +141,28 @@ module attributes {transform.with_named_sequence} { transform.yield } } + +// ----- + +#map = affine_map<(d0, d1) -> ()> +#map1 = affine_map<(d0, d1) -> (d0, d1)> +func.func @linalg_generic_fill(%arg0: tensor<7x7xf32>) -> tensor<7x7xf32> { + %cst = arith.constant 0.000000e+00 : f32 + %0 = linalg.generic {indexing_maps = [#map, #map1], iterator_types = ["parallel", "parallel"]} ins(%cst : f32) outs(%arg0 : tensor<7x7xf32>) { + ^bb0(%in: f32, %out: f32): + linalg.yield %in : f32 + } -> tensor<7x7xf32> + return %0 : tensor<7x7xf32> +} +// CHECK-LABEL: linalg_generic_fill +// CHECK-SAME: %[[ARG0:.+]]: tensor<7x7xf32>) -> tensor<7x7xf32> +// CHECK: %[[CST:.+]] = arith.constant 0.000000e+00 : f32 +// CHECK: %{{.*}} = linalg.fill ins(%[[CST]] : f32) outs(%[[ARG0]] : tensor<7x7xf32>) -> tensor<7x7xf32> + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match interface{LinalgOp} in %arg1 : (!transform.any_op) -> !transform.any_op + %1 = transform.structured.specialize %0 : (!transform.any_op) -> !transform.any_op + transform.yield + } +} diff --git a/mlir/test/Dialect/Linalg/transform-op-specialize_elemwise_binary.mlir b/mlir/test/Dialect/Linalg/transform-op-specialize_elemwise_binary.mlir new file mode 100644 index 000000000000..d45025de931c --- /dev/null +++ b/mlir/test/Dialect/Linalg/transform-op-specialize_elemwise_binary.mlir @@ -0,0 +1,76 @@ +// RUN: mlir-opt --transform-interpreter --split-input-file --verify-diagnostics %s | FileCheck %s + +#map = affine_map<(d0, d1) -> (d0, d1)> +func.func @specialize_add(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { + %0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor, tensor) outs(%arg2 : tensor) { + ^bb0(%in: f32, %in_0: f32, %out: f32): + %1 = arith.addf %in, %in_0 : f32 + linalg.yield %1 : f32 + } -> tensor + return %0 : tensor +} +// CHECK-LABEL: specialize_add +// CHECK-SAME: %[[ARG0:.+]]: tensor, %[[ARG1:.+]]: tensor, %[[ARG2:.+]]: tensor) -> tensor +// CHECK-NOT: linalg.generic +// CHECK: linalg.add ins(%[[ARG0]], %[[ARG1]] : tensor, tensor) outs(%[[ARG2]] : tensor) -> tensor + +func.func @specialize_sub(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { + %0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor, tensor) outs(%arg2 : tensor) { + ^bb0(%in: f32, %in_0: f32, %out: f32): + %1 = arith.subf %in, %in_0 : f32 + linalg.yield %1 : f32 + } -> tensor + return %0 : tensor +} +// CHECK-LABEL: specialize_sub +// CHECK-SAME: %[[ARG0:.+]]: tensor, %[[ARG1:.+]]: tensor, %[[ARG2:.+]]: tensor) -> tensor +// CHECK-NOT: linalg.generic +// CHECK: linalg.sub ins(%[[ARG0]], %[[ARG1]] : tensor, tensor) outs(%[[ARG2]] : tensor) -> tensor + +func.func @specialize_sub_swapped_operands(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { + %0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor, tensor) outs(%arg2 : tensor) { + ^bb0(%in: f32, %in_0: f32, %out: f32): + %1 = arith.subf %in_0, %in : f32 + linalg.yield %1 : f32 + } -> tensor + return %0 : tensor +} +// CHECK-LABEL: specialize_sub +// CHECK-SAME: %[[ARG0:.+]]: tensor, %[[ARG1:.+]]: tensor, %[[ARG2:.+]]: tensor) -> tensor +// CHECK-NOT: linalg.generic +// CHECK: linalg.sub ins(%[[ARG1]], %[[ARG0]] : tensor, tensor) outs(%[[ARG2]] : tensor) -> tensor + +func.func @specialize_mul(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { + %0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor, tensor) outs(%arg2 : tensor) { + ^bb0(%in: f32, %in_0: f32, %out: f32): + %1 = arith.mulf %in, %in_0 : f32 + linalg.yield %1 : f32 + } -> tensor + return %0 : tensor +} +// CHECK-LABEL: specialize_mul +// CHECK-SAME: %[[ARG0:.+]]: tensor, %[[ARG1:.+]]: tensor, %[[ARG2:.+]]: tensor) -> tensor +// CHECK-NOT: linalg.generic +// CHECK: linalg.mul ins(%[[ARG0]], %[[ARG1]] : tensor, tensor) outs(%[[ARG2]] : tensor) -> tensor + +func.func @specialize_div(%arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { + %0 = linalg.generic {indexing_maps = [#map, #map, #map], iterator_types = ["parallel", "parallel"]} ins(%arg0, %arg1 : tensor, tensor) outs(%arg2 : tensor) { + ^bb0(%in: f32, %in_0: f32, %out: f32): + %1 = arith.divf %in, %in_0 : f32 + linalg.yield %1 : f32 + } -> tensor + return %0 : tensor +} +// CHECK-LABEL: specialize_div +// CHECK-SAME: %[[ARG0:.+]]: tensor, %[[ARG1:.+]]: tensor, %[[ARG2:.+]]: tensor) -> tensor +// CHECK-NOT: linalg.generic +// CHECK: linalg.div ins(%[[ARG0]], %[[ARG1]] : tensor, tensor) outs(%[[ARG2]] : tensor) -> tensor + + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match interface{LinalgOp} in %arg0 : (!transform.any_op) -> !transform.any_op + %1 = transform.structured.specialize %0 : (!transform.any_op) -> !transform.any_op + transform.yield + } +} diff --git a/mlir/test/Dialect/Linalg/transform-op-specialize_elemwise_unary.mlir b/mlir/test/Dialect/Linalg/transform-op-specialize_elemwise_unary.mlir new file mode 100644 index 000000000000..89a8baa453e9 --- /dev/null +++ b/mlir/test/Dialect/Linalg/transform-op-specialize_elemwise_unary.mlir @@ -0,0 +1,25 @@ +// RUN: mlir-opt --transform-interpreter --split-input-file --verify-diagnostics %s | FileCheck %s + +#umap = affine_map<(d0, d1, d2) -> (d0, d1, d2)> +func.func @specialize_exp(%arg0: tensor, %arg1: tensor) -> tensor { + %0 = linalg.generic + {indexing_maps = [#umap, #umap], iterator_types = ["parallel", "parallel","parallel"]} + ins(%arg0 : tensor) outs(%arg1 : tensor) { + ^bb0(%in: f32, %out: f32): + %1 = math.exp %in : f32 + linalg.yield %1 : f32 + } -> tensor + return %0 : tensor +} +// CHECK-LABEL: specialize_exp +// CHECK-SAME: %[[ARG0:.+]]: tensor, %[[ARG1:.+]]: tensor) -> tensor +// CHECK-NOT: linalg.generic +// CHECK: linalg.exp ins(%[[ARG0]] : tensor) outs(%[[ARG1]] : tensor) -> tensor + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match interface{LinalgOp} in %arg0 : (!transform.any_op) -> !transform.any_op + %1 = transform.structured.specialize %0 : (!transform.any_op) -> !transform.any_op + transform.yield + } +} -- GitLab From 110f6a740b4f63f8eabefc24ad90e98357782949 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 20 May 2024 15:29:35 -0700 Subject: [PATCH 136/793] [SelectionDAG] Add getVPZeroExtendInReg. NFC (#92792) Use it for 2 places in LegalizeIntegerTypes that created a VP_AND. --- llvm/include/llvm/CodeGen/SelectionDAG.h | 5 +++++ .../SelectionDAG/LegalizeIntegerTypes.cpp | 11 +++-------- .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h index ed6962685f7b..96a627069046 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -991,6 +991,11 @@ public: /// value assuming it was the smaller SrcTy value. SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT); + /// Return the expression required to zero extend the Op + /// value assuming it was the smaller SrcTy value. + SDValue getVPZeroExtendInReg(SDValue Op, SDValue Mask, SDValue EVL, + const SDLoc &DL, EVT VT); + /// Convert Op, which must be of integer type, to the integer type VT, by /// either truncating it or performing either zero or sign extension as /// appropriate extension for the pointer's semantics. diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 7d3be7299523..c64e27fe4563 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -1511,10 +1511,7 @@ SDValue DAGTypeLegalizer::PromoteIntRes_VPFunnelShift(SDNode *N) { !TLI.isOperationLegalOrCustom(Opcode, VT)) { SDValue HiShift = DAG.getConstant(OldBits, DL, VT); Hi = DAG.getNode(ISD::VP_SHL, DL, VT, Hi, HiShift, Mask, EVL); - APInt Imm = APInt::getLowBitsSet(VT.getScalarSizeInBits(), - OldVT.getScalarSizeInBits()); - Lo = DAG.getNode(ISD::VP_AND, DL, VT, Lo, DAG.getConstant(Imm, DL, VT), - Mask, EVL); + Lo = DAG.getVPZeroExtendInReg(Lo, Mask, EVL, DL, OldVT); SDValue Res = DAG.getNode(ISD::VP_OR, DL, VT, Hi, Lo, Mask, EVL); Res = DAG.getNode(IsFSHR ? ISD::VP_LSHR : ISD::VP_SHL, DL, VT, Res, Amt, Mask, EVL); @@ -2377,10 +2374,8 @@ SDValue DAGTypeLegalizer::PromoteIntOp_VP_ZERO_EXTEND(SDNode *N) { // FIXME: There is no VP_ANY_EXTEND yet. Op = DAG.getNode(ISD::VP_ZERO_EXTEND, dl, VT, Op, N->getOperand(1), N->getOperand(2)); - APInt Imm = APInt::getLowBitsSet(VT.getScalarSizeInBits(), - N->getOperand(0).getScalarValueSizeInBits()); - return DAG.getNode(ISD::VP_AND, dl, VT, Op, DAG.getConstant(Imm, dl, VT), - N->getOperand(1), N->getOperand(2)); + return DAG.getVPZeroExtendInReg(Op, N->getOperand(1), N->getOperand(2), dl, + N->getOperand(0).getValueType()); } SDValue DAGTypeLegalizer::PromoteIntOp_FIX(SDNode *N) { diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 72685a2d7721..777bbf071732 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1540,6 +1540,25 @@ SDValue SelectionDAG::getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT) { return getNode(ISD::AND, DL, OpVT, Op, getConstant(Imm, DL, OpVT)); } +SDValue SelectionDAG::getVPZeroExtendInReg(SDValue Op, SDValue Mask, + SDValue EVL, const SDLoc &DL, + EVT VT) { + EVT OpVT = Op.getValueType(); + assert(VT.isInteger() && OpVT.isInteger() && + "Cannot getVPZeroExtendInReg FP types"); + assert(VT.isVector() && OpVT.isVector() && + "getVPZeroExtendInReg type and operand type should be vector!"); + assert(VT.getVectorElementCount() == OpVT.getVectorElementCount() && + "Vector element counts must match in getZeroExtendInReg"); + assert(VT.bitsLE(OpVT) && "Not extending!"); + if (OpVT == VT) + return Op; + APInt Imm = APInt::getLowBitsSet(OpVT.getScalarSizeInBits(), + VT.getScalarSizeInBits()); + return getNode(ISD::VP_AND, DL, OpVT, Op, getConstant(Imm, DL, OpVT), Mask, + EVL); +} + SDValue SelectionDAG::getPtrExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT) { // Only unsigned pointer semantics are supported right now. In the future this // might delegate to TLI to check pointer signedness. -- GitLab From 8018e4c569d34b5913a4cc78f08f25f778dec866 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 20 May 2024 15:30:03 -0700 Subject: [PATCH 137/793] [LegalizeTypes] Use SelectionDAG::SplitVector to simplify some code. NFC (#92816) --- .../SelectionDAG/LegalizeVectorTypes.cpp | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp index dca5a481fbd0..ec0513591566 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -2911,18 +2911,10 @@ void DAGTypeLegalizer::SplitVecRes_VECTOR_REVERSE(SDNode *N, SDValue &Lo, void DAGTypeLegalizer::SplitVecRes_VECTOR_SPLICE(SDNode *N, SDValue &Lo, SDValue &Hi) { - EVT VT = N->getValueType(0); SDLoc DL(N); - EVT LoVT, HiVT; - std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VT); - SDValue Expanded = TLI.expandVectorSplice(N, DAG); - Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, LoVT, Expanded, - DAG.getVectorIdxConstant(0, DL)); - Hi = - DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HiVT, Expanded, - DAG.getVectorIdxConstant(LoVT.getVectorMinNumElements(), DL)); + std::tie(Lo, Hi) = DAG.SplitVector(Expanded, DL); } void DAGTypeLegalizer::SplitVecRes_VP_REVERSE(SDNode *N, SDValue &Lo, @@ -2967,12 +2959,7 @@ void DAGTypeLegalizer::SplitVecRes_VP_REVERSE(SDNode *N, SDValue &Lo, SDValue Load = DAG.getLoadVP(VT, DL, Store, StackPtr, Mask, EVL, LoadMMO); - auto [LoVT, HiVT] = DAG.GetSplitDestVTs(VT); - Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, LoVT, Load, - DAG.getVectorIdxConstant(0, DL)); - Hi = - DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HiVT, Load, - DAG.getVectorIdxConstant(LoVT.getVectorMinNumElements(), DL)); + std::tie(Lo, Hi) = DAG.SplitVector(Load, DL); } void DAGTypeLegalizer::SplitVecRes_VECTOR_DEINTERLEAVE(SDNode *N) { -- GitLab From e8dc8d614ada201e250fbf075241b2b6180943b5 Mon Sep 17 00:00:00 2001 From: royitaqi Date: Mon, 20 May 2024 15:49:46 -0700 Subject: [PATCH 138/793] Add new Python API `SBCommandInterpreter::GetTranscript()` (#90703) # Motivation Currently, the user can already get the "transcript" (for "what is the transcript", see `CommandInterpreter::SaveTranscript`). However, the only way to obtain the transcript data as a user is to first destroy the debugger, then read the save directory. Note that destroy-callbacks cannot be used, because 1\ transcript data is private to the command interpreter (see `CommandInterpreter.h`), and 2\ the writing of the transcript is *after* the invocation of destory-callbacks (see `Debugger::Destroy`). So basically, there is no way to obtain the transcript: * during the lifetime of a debugger (including the destroy-callbacks, which often performs logging tasks, where the transcript can be useful) * without relying on external storage In theory, there are other ways for user to obtain transcript data during a debugger's life cycle: * Use Python API and intercept commands and results. * Use CLI and record console input/output. However, such ways rely on the client's setup and are not supported natively by LLDB. # Proposal Add a new Python API `SBCommandInterpreter::GetTranscript()`. Goals: * It can be called at any time during the debugger's life cycle, including in destroy-callbacks. * It returns data in-memory. Structured data: * To make data processing easier, the return type is `SBStructuredData`. See comments in code for how the data is organized. * In the future, `SaveTranscript` can be updated to write different formats using such data (e.g. JSON). This is probably accompanied by a new setting (e.g. `interpreter.save-session-format`). # Alternatives The return type can also be `std::vector>`. This will make implementation easier, without having to translate it to `SBStructuredData`. On the other hand, `SBStructuredData` can convert to JSON easily, so it's more convenient for user to process. # Privacy Both user commands and output/error in the transcript can contain privacy data. However, as mentioned, the transcript is already available to the user. The addition of the new API doesn't increase the level of risk. In fact, it _lowers_ the risk of privacy data being leaked later on, by avoiding writing such data to external storage. Once the user (or their code) gets the transcript, it will be their responsibility to make sure that any required privacy policies are guaranteed. # Tests ``` bin/llvm-lit -sv ../external/llvm-project/lldb/test/API/python_api/interpreter/TestCommandInterpreterAPI.py ``` ``` bin/llvm-lit -sv ../external/llvm-project/lldb/test/API/commands/session/save/TestSessionSave.py ``` --------- Co-authored-by: Roy Shi Co-authored-by: Med Ismail Bennani --- lldb/include/lldb/API/SBCommandInterpreter.h | 8 + .../lldb/Interpreter/CommandInterpreter.h | 18 ++ lldb/source/API/SBCommandInterpreter.cpp | 16 ++ .../source/Interpreter/CommandInterpreter.cpp | 43 ++++- .../Interpreter/InterpreterProperties.td | 4 + .../commands/session/save/TestSessionSave.py | 12 ++ .../interpreter/TestCommandInterpreterAPI.py | 172 +++++++++++++++++- lldb/test/API/python_api/interpreter/main.c | 5 +- 8 files changed, 270 insertions(+), 8 deletions(-) diff --git a/lldb/include/lldb/API/SBCommandInterpreter.h b/lldb/include/lldb/API/SBCommandInterpreter.h index ba2e049204b8..8ac36344b3a7 100644 --- a/lldb/include/lldb/API/SBCommandInterpreter.h +++ b/lldb/include/lldb/API/SBCommandInterpreter.h @@ -318,6 +318,14 @@ public: SBStructuredData GetStatistics(); + /// Returns a list of handled commands, output and error. Each element in + /// the list is a dictionary with the following keys/values: + /// - "command" (string): The command that was executed. + /// - "output" (string): The output of the command. Empty ("") if no output. + /// - "error" (string): The error of the command. Empty ("") if no error. + /// - "seconds" (float): The time it took to execute the command. + SBStructuredData GetTranscript(); + protected: friend class lldb_private::CommandPluginInterfaceImplementation; diff --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h index 70a55a77465b..ccc30cf4f1a8 100644 --- a/lldb/include/lldb/Interpreter/CommandInterpreter.h +++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h @@ -22,6 +22,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StringList.h" +#include "lldb/Utility/StructuredData.h" #include "lldb/lldb-forward.h" #include "lldb/lldb-private.h" @@ -560,6 +561,9 @@ public: bool GetPromptOnQuit() const; void SetPromptOnQuit(bool enable); + bool GetSaveTranscript() const; + void SetSaveTranscript(bool enable); + bool GetSaveSessionOnQuit() const; void SetSaveSessionOnQuit(bool enable); @@ -647,6 +651,7 @@ public: } llvm::json::Value GetStatistics(); + const StructuredData::Array &GetTranscript() const; protected: friend class Debugger; @@ -765,7 +770,20 @@ private: typedef llvm::StringMap CommandUsageMap; CommandUsageMap m_command_usages; + /// Turn on settings `interpreter.save-transcript` for LLDB to populate + /// this stream. Otherwise this stream is empty. StreamString m_transcript_stream; + + /// Contains a list of handled commands and their details. Each element in + /// the list is a dictionary with the following keys/values: + /// - "command" (string): The command that was executed. + /// - "output" (string): The output of the command. Empty ("") if no output. + /// - "error" (string): The error of the command. Empty ("") if no error. + /// - "seconds" (float): The time it took to execute the command. + /// + /// Turn on settings `interpreter.save-transcript` for LLDB to populate + /// this list. Otherwise this list is empty. + StructuredData::Array m_transcript; }; } // namespace lldb_private diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp index 83c0951c56db..7a3547328368 100644 --- a/lldb/source/API/SBCommandInterpreter.cpp +++ b/lldb/source/API/SBCommandInterpreter.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Utility/StructuredData.h" #include "lldb/lldb-types.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -571,6 +572,21 @@ SBStructuredData SBCommandInterpreter::GetStatistics() { return data; } +SBStructuredData SBCommandInterpreter::GetTranscript() { + LLDB_INSTRUMENT_VA(this); + + SBStructuredData data; + if (IsValid()) + // A deep copy is performed by `std::make_shared` on the + // `StructuredData::Array`, via its implicitly-declared copy constructor. + // This ensures thread-safety between the user changing the returned + // `SBStructuredData` and the `CommandInterpreter` changing its internal + // `m_transcript`. + data.m_impl_up->SetObjectSP( + std::make_shared(m_opaque_ptr->GetTranscript())); + return data; +} + lldb::SBCommand SBCommandInterpreter::AddMultiwordCommand(const char *name, const char *help) { LLDB_INSTRUMENT_VA(this, name, help); diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index 4c58ecc3c184..811726e30af4 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -51,6 +51,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/State.h" #include "lldb/Utility/Stream.h" +#include "lldb/Utility/StructuredData.h" #include "lldb/Utility/Timer.h" #include "lldb/Host/Config.h" @@ -161,6 +162,17 @@ void CommandInterpreter::SetPromptOnQuit(bool enable) { SetPropertyAtIndex(idx, enable); } +bool CommandInterpreter::GetSaveTranscript() const { + const uint32_t idx = ePropertySaveTranscript; + return GetPropertyAtIndexAs( + idx, g_interpreter_properties[idx].default_uint_value != 0); +} + +void CommandInterpreter::SetSaveTranscript(bool enable) { + const uint32_t idx = ePropertySaveTranscript; + SetPropertyAtIndex(idx, enable); +} + bool CommandInterpreter::GetSaveSessionOnQuit() const { const uint32_t idx = ePropertySaveSessionOnQuit; return GetPropertyAtIndexAs( @@ -1889,7 +1901,16 @@ bool CommandInterpreter::HandleCommand(const char *command_line, else add_to_history = (lazy_add_to_history == eLazyBoolYes); - m_transcript_stream << "(lldb) " << command_line << '\n'; + // The same `transcript_item` will be used below to add output and error of + // the command. + StructuredData::DictionarySP transcript_item; + if (GetSaveTranscript()) { + m_transcript_stream << "(lldb) " << command_line << '\n'; + + transcript_item = std::make_shared(); + transcript_item->AddStringItem("command", command_line); + m_transcript.AddItem(transcript_item); + } bool empty_command = false; bool comment_command = false; @@ -1994,7 +2015,7 @@ bool CommandInterpreter::HandleCommand(const char *command_line, // Take care of things like setting up the history command & calling the // appropriate Execute method on the CommandObject, with the appropriate // arguments. - + StatsDuration execute_time; if (cmd_obj != nullptr) { bool generate_repeat_command = add_to_history; // If we got here when empty_command was true, then this command is a @@ -2035,14 +2056,24 @@ bool CommandInterpreter::HandleCommand(const char *command_line, log, "HandleCommand, command line after removing command name(s): '%s'", remainder.c_str()); + ElapsedTime elapsed(execute_time); cmd_obj->Execute(remainder.c_str(), result); } LLDB_LOGF(log, "HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed")); - m_transcript_stream << result.GetOutputData(); - m_transcript_stream << result.GetErrorData(); + // To test whether or not transcript should be saved, `transcript_item` is + // used instead of `GetSaveTrasncript()`. This is because the latter will + // fail when the command is "settings set interpreter.save-transcript true". + if (transcript_item) { + m_transcript_stream << result.GetOutputData(); + m_transcript_stream << result.GetErrorData(); + + transcript_item->AddStringItem("output", result.GetOutputData()); + transcript_item->AddStringItem("error", result.GetErrorData()); + transcript_item->AddFloatItem("seconds", execute_time.get().count()); + } return result.Succeeded(); } @@ -3554,3 +3585,7 @@ llvm::json::Value CommandInterpreter::GetStatistics() { stats.try_emplace(command_usage.getKey(), command_usage.getValue()); return stats; } + +const StructuredData::Array &CommandInterpreter::GetTranscript() const { + return m_transcript; +} diff --git a/lldb/source/Interpreter/InterpreterProperties.td b/lldb/source/Interpreter/InterpreterProperties.td index 2155ee61ccff..a5fccbbca091 100644 --- a/lldb/source/Interpreter/InterpreterProperties.td +++ b/lldb/source/Interpreter/InterpreterProperties.td @@ -9,6 +9,10 @@ let Definition = "interpreter" in { Global, DefaultTrue, Desc<"If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case.">; + def SaveTranscript: Property<"save-transcript", "Boolean">, + Global, + DefaultFalse, + Desc<"If true, commands will be saved into a transcript buffer for user access.">; def SaveSessionOnQuit: Property<"save-session-on-quit", "Boolean">, Global, DefaultFalse, diff --git a/lldb/test/API/commands/session/save/TestSessionSave.py b/lldb/test/API/commands/session/save/TestSessionSave.py index 172a76452304..98985c66010b 100644 --- a/lldb/test/API/commands/session/save/TestSessionSave.py +++ b/lldb/test/API/commands/session/save/TestSessionSave.py @@ -25,6 +25,12 @@ class SessionSaveTestCase(TestBase): raw = "" interpreter = self.dbg.GetCommandInterpreter() + # Make sure "save-transcript" is on, so that all the following setings + # and commands are saved into the trasncript. Note that this cannot be + # a part of the `settings`, because this command itself won't be saved + # into the transcript. + self.runCmd("settings set interpreter.save-transcript true") + settings = [ "settings set interpreter.echo-commands true", "settings set interpreter.echo-comment-commands true", @@ -95,6 +101,12 @@ class SessionSaveTestCase(TestBase): raw = "" interpreter = self.dbg.GetCommandInterpreter() + # Make sure "save-transcript" is on, so that all the following setings + # and commands are saved into the trasncript. Note that this cannot be + # a part of the `settings`, because this command itself won't be saved + # into the transcript. + self.runCmd("settings set interpreter.save-transcript true") + td = tempfile.TemporaryDirectory() settings = [ diff --git a/lldb/test/API/python_api/interpreter/TestCommandInterpreterAPI.py b/lldb/test/API/python_api/interpreter/TestCommandInterpreterAPI.py index 8f9fbfc255bb..95643eef0d34 100644 --- a/lldb/test/API/python_api/interpreter/TestCommandInterpreterAPI.py +++ b/lldb/test/API/python_api/interpreter/TestCommandInterpreterAPI.py @@ -1,5 +1,6 @@ """Test the SBCommandInterpreter APIs.""" +import json import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * @@ -15,8 +16,7 @@ class CommandInterpreterAPICase(TestBase): # Find the line number to break on inside main.cpp. self.line = line_number("main.c", "Hello world.") - def test_with_process_launch_api(self): - """Test the SBCommandInterpreter APIs.""" + def buildAndCreateTarget(self): self.build() exe = self.getBuildArtifact("a.out") @@ -27,6 +27,11 @@ class CommandInterpreterAPICase(TestBase): # Retrieve the associated command interpreter from our debugger. ci = self.dbg.GetCommandInterpreter() self.assertTrue(ci, VALID_COMMAND_INTERPRETER) + return ci + + def test_with_process_launch_api(self): + """Test the SBCommandInterpreter APIs.""" + ci = self.buildAndCreateTarget() # Exercise some APIs.... @@ -85,3 +90,166 @@ class CommandInterpreterAPICase(TestBase): self.assertEqual(res.GetOutput(), "") self.assertIsNotNone(res.GetError()) self.assertEqual(res.GetError(), "") + + def getTranscriptAsPythonObject(self, ci): + """Retrieve the transcript and convert it into a Python object""" + structured_data = ci.GetTranscript() + self.assertTrue(structured_data.IsValid()) + + stream = lldb.SBStream() + self.assertTrue(stream) + + error = structured_data.GetAsJSON(stream) + self.assertSuccess(error) + + return json.loads(stream.GetData()) + + def test_structured_transcript(self): + """Test structured transcript generation and retrieval.""" + ci = self.buildAndCreateTarget() + + # Make sure the "save-transcript" setting is on + self.runCmd("settings set interpreter.save-transcript true") + + # Send a few commands through the command interpreter. + # + # Using `ci.HandleCommand` because some commands will fail so that we + # can test the "error" field in the saved transcript. + res = lldb.SBCommandReturnObject() + ci.HandleCommand("version", res) + ci.HandleCommand("an-unknown-command", res) + ci.HandleCommand("breakpoint set -f main.c -l %d" % self.line, res) + ci.HandleCommand("r", res) + ci.HandleCommand("p a", res) + ci.HandleCommand("statistics dump", res) + total_number_of_commands = 6 + + # Get transcript as python object + transcript = self.getTranscriptAsPythonObject(ci) + + # All commands should have expected fields. + for command in transcript: + self.assertIn("command", command) + self.assertIn("output", command) + self.assertIn("error", command) + self.assertIn("seconds", command) + + # The following validates individual commands in the transcript. + # + # Notes: + # 1. Some of the asserts rely on the exact output format of the + # commands. Hopefully we are not changing them any time soon. + # 2. We are removing the "seconds" field from each command, so that + # some of the validations below can be easier / more readable. + for command in transcript: + del(command["seconds"]) + + # (lldb) version + self.assertEqual(transcript[0]["command"], "version") + self.assertIn("lldb version", transcript[0]["output"]) + self.assertEqual(transcript[0]["error"], "") + + # (lldb) an-unknown-command + self.assertEqual(transcript[1], + { + "command": "an-unknown-command", + "output": "", + "error": "error: 'an-unknown-command' is not a valid command.\n", + }) + + # (lldb) breakpoint set -f main.c -l + self.assertEqual(transcript[2]["command"], "breakpoint set -f main.c -l %d" % self.line) + # Breakpoint 1: where = a.out`main + 29 at main.c:5:3, address = 0x0000000100000f7d + self.assertIn("Breakpoint 1: where = a.out`main ", transcript[2]["output"]) + self.assertEqual(transcript[2]["error"], "") + + # (lldb) r + self.assertEqual(transcript[3]["command"], "r") + # Process 25494 launched: '/TestCommandInterpreterAPI.test_structured_transcript/a.out' (x86_64) + self.assertIn("Process", transcript[3]["output"]) + self.assertIn("launched", transcript[3]["output"]) + self.assertEqual(transcript[3]["error"], "") + + # (lldb) p a + self.assertEqual(transcript[4], + { + "command": "p a", + "output": "(int) 123\n", + "error": "", + }) + + # (lldb) statistics dump + statistics_dump = json.loads(transcript[5]["output"]) + # Dump result should be valid JSON + self.assertTrue(statistics_dump is not json.JSONDecodeError) + # Dump result should contain expected fields + self.assertIn("commands", statistics_dump) + self.assertIn("memory", statistics_dump) + self.assertIn("modules", statistics_dump) + self.assertIn("targets", statistics_dump) + + def test_save_transcript_setting_default(self): + ci = self.buildAndCreateTarget() + res = lldb.SBCommandReturnObject() + + # The setting's default value should be "false" + self.runCmd("settings show interpreter.save-transcript", "interpreter.save-transcript (boolean) = false\n") + # self.assertEqual(res.GetOutput(), ) + + def test_save_transcript_setting_off(self): + ci = self.buildAndCreateTarget() + + # Make sure the setting is off + self.runCmd("settings set interpreter.save-transcript false") + + # The transcript should be empty after running a command + self.runCmd("version") + transcript = self.getTranscriptAsPythonObject(ci) + self.assertEqual(transcript, []) + + def test_save_transcript_setting_on(self): + ci = self.buildAndCreateTarget() + res = lldb.SBCommandReturnObject() + + # Make sure the setting is on + self.runCmd("settings set interpreter.save-transcript true") + + # The transcript should contain one item after running a command + self.runCmd("version") + transcript = self.getTranscriptAsPythonObject(ci) + self.assertEqual(len(transcript), 1) + self.assertEqual(transcript[0]["command"], "version") + + def test_save_transcript_returns_copy(self): + """ + Test that the returned structured data is *at least* a shallow copy. + + We believe that a deep copy *is* performed in `SBCommandInterpreter::GetTranscript`. + However, the deep copy cannot be tested and doesn't need to be tested, + because there is no logic in the command interpreter to modify a + transcript item (representing a command) after it has been returned. + """ + ci = self.buildAndCreateTarget() + + # Make sure the setting is on + self.runCmd("settings set interpreter.save-transcript true") + + # Run commands and get the transcript as structured data + self.runCmd("version") + structured_data_1 = ci.GetTranscript() + self.assertTrue(structured_data_1.IsValid()) + self.assertEqual(structured_data_1.GetSize(), 1) + self.assertEqual(structured_data_1.GetItemAtIndex(0).GetValueForKey("command").GetStringValue(100), "version") + + # Run some more commands and get the transcript as structured data again + self.runCmd("help") + structured_data_2 = ci.GetTranscript() + self.assertTrue(structured_data_2.IsValid()) + self.assertEqual(structured_data_2.GetSize(), 2) + self.assertEqual(structured_data_2.GetItemAtIndex(0).GetValueForKey("command").GetStringValue(100), "version") + self.assertEqual(structured_data_2.GetItemAtIndex(1).GetValueForKey("command").GetStringValue(100), "help") + + # Now, the first structured data should remain unchanged + self.assertTrue(structured_data_1.IsValid()) + self.assertEqual(structured_data_1.GetSize(), 1) + self.assertEqual(structured_data_1.GetItemAtIndex(0).GetValueForKey("command").GetStringValue(100), "version") diff --git a/lldb/test/API/python_api/interpreter/main.c b/lldb/test/API/python_api/interpreter/main.c index 277aa54a4eea..366ffde5fdef 100644 --- a/lldb/test/API/python_api/interpreter/main.c +++ b/lldb/test/API/python_api/interpreter/main.c @@ -1,6 +1,7 @@ #include int main(int argc, char const *argv[]) { - printf("Hello world.\n"); - return 0; + int a = 123; + printf("Hello world.\n"); + return 0; } -- GitLab From 9f62775038b9135709a2c3c7ea97c944278967a2 Mon Sep 17 00:00:00 2001 From: royitaqi Date: Mon, 20 May 2024 15:51:42 -0700 Subject: [PATCH 139/793] SBDebugger: Add new APIs `AddDestroyCallback` and `RemoveDestroyCallback` (#89868) # Motivation Individual callers of `SBDebugger::SetDestroyCallback()` might think that they have registered their callback and expect it to be called when the debugger is destroyed. In reality, only the last caller survives, and all previous callers are forgotten, which might be a surprise to them. Worse, if this is called in a race condition, which callback survives is less predictable, which may case confusing behavior elsewhere. # This PR Allows multiple destroy callbacks to be registered and all called when the debugger is destroyed. **EDIT**: Adds two new APIs: `AddDestroyCallback()` and `ClearDestroyCallback()`. `SetDestroyCallback()` will first clear then add the given callback. Tests are added for the new APIs. ## Tests ``` bin/llvm-lit -sv ../external/llvm-project/lldb/test/API/python_api/debugger/TestDebuggerAPI.py ``` ## (out-dated, see comments below) Semantic change to `SetDestroyCallback()` ~~Currently, the method overwrites the old callback with the new one. With this PR, it will NOT overwrite. Instead, it will hold on to both. Both callbacks get called during destroy.~~ ~~**Risk**: Although the documentation of `SetDestroyCallback()` (see [C++](https://lldb.llvm.org/cpp_reference/classlldb_1_1SBDebugger.html#afa1649d9453a376b5c95888b5a0cb4ec) and [python](https://lldb.llvm.org/python_api/lldb.SBDebugger.html#lldb.SBDebugger.SetDestroyCallback)) doesn't really specify the behavior, there is a risk: if existing call sites rely on the "overwrite" behavior, they will be surprised because now the old callback will get called. But as the above said, the current behavior of "overwrite" itself might be unintended, so I don't anticipate users to rely on this behavior. In short, this risk might be less of a problem if we correct it sooner rather than later (which is what this PR is trying to do).~~ ## (out-dated, see comments below) Implementation ~~The implementation holds a `std::vector>`. When `SetDestroyCallback()` is called, callbacks and batons are appended to the `std::vector`. When destroy event happen, the `(callback, baton)` pairs are invoked FIFO. Finally, the `std::vector` is cleared.~~ # (out-dated, see comments below) Alternatives considered ~~Instead of changing `SetDestroyCallback()`, a new method `AddDestroyCallback()` can be added, which use the same `std::vector>` implementation. Together with `ClearDestroyCallback()` (see below), they will replace and deprecate `SetDestroyCallback()`. Meanwhile, in order to be backward compatible, `SetDestroyCallback()` need to be updated to clear the `std::vector` and then add the new callback. Pros: The end state is semantically more correct. Cons: More steps to take; potentially maintaining an "incorrect" behavior (of "overwrite").~~ ~~A new method `ClearDestroyCallback()` can be added. Might be unnecessary at this point, because workflows which need to set then clear callbacks may exist but shouldn't be too common at least for now. Such method can be added later when needed.~~ ~~The `std::vector` may bring slight performance drawback if its implementation doesn't handle small size efficiently. However, even if that's the case, this path should be very cold (only used during init and destroy). Such performance drawback should be negligible.~~ ~~A different implementation was also considered. Instead of using `std::vector`, the current `m_destroy_callback` field can be kept unchanged. When `SetDestroyCallback()` is called, a lambda function can be stored into `m_destroy_callback`. This lambda function will first call the old callback, then the new one. This way, `std::vector` is avoided. However, this implementation is more complex, thus less readable, with not much perf to gain.~~ --------- Co-authored-by: Roy Shi --- lldb/include/lldb/API/SBDebugger.h | 13 ++ lldb/include/lldb/Core/Debugger.h | 31 ++++- lldb/include/lldb/lldb-types.h | 2 + lldb/source/API/SBDebugger.cpp | 20 +++ lldb/source/Core/Debugger.cpp | 45 ++++++- .../python_api/debugger/TestDebuggerAPI.py | 121 ++++++++++++++++++ 6 files changed, 225 insertions(+), 7 deletions(-) diff --git a/lldb/include/lldb/API/SBDebugger.h b/lldb/include/lldb/API/SBDebugger.h index 7333cd57ad31..af19b1faf3bf 100644 --- a/lldb/include/lldb/API/SBDebugger.h +++ b/lldb/include/lldb/API/SBDebugger.h @@ -328,9 +328,22 @@ public: void SetLoggingCallback(lldb::LogOutputCallback log_callback, void *baton); + /// Clear all previously added callbacks and only add the given one. + LLDB_DEPRECATED_FIXME("Use AddDestroyCallback and RemoveDestroyCallback", + "AddDestroyCallback") void SetDestroyCallback(lldb::SBDebuggerDestroyCallback destroy_callback, void *baton); + /// Add a callback for when the debugger is destroyed. Return a token, which + /// can be used to remove said callback. Multiple callbacks can be added by + /// calling this function multiple times, and will be invoked in FIFO order. + lldb::callback_token_t + AddDestroyCallback(lldb::SBDebuggerDestroyCallback destroy_callback, + void *baton); + + /// Remove the specified callback. Return true if successful. + bool RemoveDestroyCallback(lldb::callback_token_t token); + #ifndef SWIG LLDB_DEPRECATED_FIXME("Use DispatchInput(const void *, size_t)", "DispatchInput(const void *, size_t)") diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h index ea994bf8c28d..a72c2596cc2c 100644 --- a/lldb/include/lldb/Core/Debugger.h +++ b/lldb/include/lldb/Core/Debugger.h @@ -40,6 +40,7 @@ #include "lldb/lldb-types.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DynamicLibrary.h" @@ -559,10 +560,25 @@ public: static void ReportSymbolChange(const ModuleSpec &module_spec); + /// DEPRECATED: We used to only support one Destroy callback. Now that we + /// support Add and Remove, you should only remove callbacks that you added. + /// Use Add and Remove instead. + /// + /// Clear all previously added callbacks and only add the given one. void SetDestroyCallback(lldb_private::DebuggerDestroyCallback destroy_callback, void *baton); + /// Add a callback for when the debugger is destroyed. Return a token, which + /// can be used to remove said callback. Multiple callbacks can be added by + /// calling this function multiple times, and will be invoked in FIFO order. + lldb::callback_token_t + AddDestroyCallback(lldb_private::DebuggerDestroyCallback destroy_callback, + void *baton); + + /// Remove the specified callback. Return true if successful. + bool RemoveDestroyCallback(lldb::callback_token_t token); + /// Manually start the global event handler thread. It is useful to plugins /// that directly use the \a lldb_private namespace and want to use the /// debugger's default event handler thread instead of defining their own. @@ -721,8 +737,19 @@ protected: lldb::TargetSP m_dummy_target_sp; Diagnostics::CallbackID m_diagnostics_callback_id; - lldb_private::DebuggerDestroyCallback m_destroy_callback = nullptr; - void *m_destroy_callback_baton = nullptr; + std::mutex m_destroy_callback_mutex; + lldb::callback_token_t m_destroy_callback_next_token = 0; + struct DestroyCallbackInfo { + DestroyCallbackInfo() {} + DestroyCallbackInfo(lldb::callback_token_t token, + lldb_private::DebuggerDestroyCallback callback, + void *baton) + : token(token), callback(callback), baton(baton) {} + lldb::callback_token_t token; + lldb_private::DebuggerDestroyCallback callback; + void *baton; + }; + llvm::SmallVector m_destroy_callbacks; uint32_t m_interrupt_requested = 0; ///< Tracks interrupt requests std::mutex m_interrupt_mutex; diff --git a/lldb/include/lldb/lldb-types.h b/lldb/include/lldb/lldb-types.h index d60686e33142..8e717c62d325 100644 --- a/lldb/include/lldb/lldb-types.h +++ b/lldb/include/lldb/lldb-types.h @@ -62,12 +62,14 @@ typedef void *thread_arg_t; // Host thread argument type typedef void *thread_result_t; // Host thread result type typedef void *(*thread_func_t)(void *); // Host thread function type typedef int pipe_t; // Host pipe type +typedef int callback_token_t; #endif // _WIN32 #define LLDB_INVALID_PROCESS ((lldb::process_t)-1) #define LLDB_INVALID_HOST_THREAD ((lldb::thread_t)NULL) #define LLDB_INVALID_PIPE ((lldb::pipe_t)-1) +#define LLDB_INVALID_CALLBACK_TOKEN ((lldb::callback_token_t) - 1) typedef void (*LogOutputCallback)(const char *, void *baton); typedef bool (*CommandOverrideCallback)(void *baton, const char **argv); diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp index 9c662dfbf441..7ef0d6efd4aa 100644 --- a/lldb/source/API/SBDebugger.cpp +++ b/lldb/source/API/SBDebugger.cpp @@ -1695,6 +1695,26 @@ void SBDebugger::SetDestroyCallback( } } +lldb::callback_token_t +SBDebugger::AddDestroyCallback(lldb::SBDebuggerDestroyCallback destroy_callback, + void *baton) { + LLDB_INSTRUMENT_VA(this, destroy_callback, baton); + + if (m_opaque_sp) + return m_opaque_sp->AddDestroyCallback(destroy_callback, baton); + + return LLDB_INVALID_CALLBACK_TOKEN; +} + +bool SBDebugger::RemoveDestroyCallback(lldb::callback_token_t token) { + LLDB_INSTRUMENT_VA(this, token); + + if (m_opaque_sp) + return m_opaque_sp->RemoveDestroyCallback(token); + + return false; +} + SBTrace SBDebugger::LoadTraceFromFile(SBError &error, const SBFileSpec &trace_description_file) { diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 9951fbcd3e7c..309e01e45658 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -743,9 +743,22 @@ DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback, } void Debugger::HandleDestroyCallback() { - if (m_destroy_callback) { - m_destroy_callback(GetID(), m_destroy_callback_baton); - m_destroy_callback = nullptr; + const lldb::user_id_t user_id = GetID(); + // Invoke and remove all the callbacks in an FIFO order. Callbacks which are + // added during this loop will be appended, invoked and then removed last. + // Callbacks which are removed during this loop will not be invoked. + while (true) { + DestroyCallbackInfo callback_info; + { + std::lock_guard guard(m_destroy_callback_mutex); + if (m_destroy_callbacks.empty()) + break; + // Pop the first item in the list + callback_info = m_destroy_callbacks.front(); + m_destroy_callbacks.erase(m_destroy_callbacks.begin()); + } + // Call the destroy callback with user id and baton + callback_info.callback(user_id, callback_info.baton); } } @@ -1427,8 +1440,30 @@ void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback, void Debugger::SetDestroyCallback( lldb_private::DebuggerDestroyCallback destroy_callback, void *baton) { - m_destroy_callback = destroy_callback; - m_destroy_callback_baton = baton; + std::lock_guard guard(m_destroy_callback_mutex); + m_destroy_callbacks.clear(); + const lldb::callback_token_t token = m_destroy_callback_next_token++; + m_destroy_callbacks.emplace_back(token, destroy_callback, baton); +} + +lldb::callback_token_t Debugger::AddDestroyCallback( + lldb_private::DebuggerDestroyCallback destroy_callback, void *baton) { + std::lock_guard guard(m_destroy_callback_mutex); + const lldb::callback_token_t token = m_destroy_callback_next_token++; + m_destroy_callbacks.emplace_back(token, destroy_callback, baton); + return token; +} + +bool Debugger::RemoveDestroyCallback(lldb::callback_token_t token) { + std::lock_guard guard(m_destroy_callback_mutex); + for (auto it = m_destroy_callbacks.begin(); it != m_destroy_callbacks.end(); + ++it) { + if (it->token == token) { + m_destroy_callbacks.erase(it); + return true; + } + } + return false; } static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id, diff --git a/lldb/test/API/python_api/debugger/TestDebuggerAPI.py b/lldb/test/API/python_api/debugger/TestDebuggerAPI.py index 522de2466012..29b8cfadd947 100644 --- a/lldb/test/API/python_api/debugger/TestDebuggerAPI.py +++ b/lldb/test/API/python_api/debugger/TestDebuggerAPI.py @@ -161,3 +161,124 @@ class DebuggerAPITestCase(TestBase): original_dbg_id = self.dbg.GetID() self.dbg.Destroy(self.dbg) self.assertEqual(destroy_dbg_id, original_dbg_id) + + def test_AddDestroyCallback(self): + original_dbg_id = self.dbg.GetID() + called = [] + + def foo(dbg_id): + # Need nonlocal to modify closure variable. + nonlocal called + called += [('foo', dbg_id)] + + def bar(dbg_id): + # Need nonlocal to modify closure variable. + nonlocal called + called += [('bar', dbg_id)] + + token_foo = self.dbg.AddDestroyCallback(foo) + token_bar = self.dbg.AddDestroyCallback(bar) + self.dbg.Destroy(self.dbg) + + # Should call both `foo()` and `bar()`. + self.assertEqual(called, [ + ('foo', original_dbg_id), + ('bar', original_dbg_id), + ]) + + def test_RemoveDestroyCallback(self): + original_dbg_id = self.dbg.GetID() + called = [] + + def foo(dbg_id): + # Need nonlocal to modify closure variable. + nonlocal called + called += [('foo', dbg_id)] + + def bar(dbg_id): + # Need nonlocal to modify closure variable. + nonlocal called + called += [('bar', dbg_id)] + + token_foo = self.dbg.AddDestroyCallback(foo) + token_bar = self.dbg.AddDestroyCallback(bar) + ret = self.dbg.RemoveDestroyCallback(token_foo) + self.dbg.Destroy(self.dbg) + + # `Remove` should be successful + self.assertTrue(ret) + # Should only call `bar()` + self.assertEqual(called, [('bar', original_dbg_id)]) + + def test_RemoveDestroyCallback_invalid_token(self): + original_dbg_id = self.dbg.GetID() + magic_token_that_should_not_exist = 32413 + called = [] + + def foo(dbg_id): + # Need nonlocal to modify closure variable. + nonlocal called + called += [('foo', dbg_id)] + + token_foo = self.dbg.AddDestroyCallback(foo) + ret = self.dbg.RemoveDestroyCallback(magic_token_that_should_not_exist) + self.dbg.Destroy(self.dbg) + + # `Remove` should be unsuccessful + self.assertFalse(ret) + # Should call `foo()` + self.assertEqual(called, [('foo', original_dbg_id)]) + + def test_HandleDestroyCallback(self): + """ + Validates: + 1. AddDestroyCallback and RemoveDestroyCallback work during debugger destroy. + 2. HandleDestroyCallback invokes all callbacks in FIFO order. + """ + original_dbg_id = self.dbg.GetID() + events = [] + bar_token = None + + def foo(dbg_id): + # Need nonlocal to modify closure variable. + nonlocal events + events.append(('foo called', dbg_id)) + + def bar(dbg_id): + # Need nonlocal to modify closure variable. + nonlocal events + events.append(('bar called', dbg_id)) + + def add_foo(dbg_id): + # Need nonlocal to modify closure variable. + nonlocal events + events.append(('add_foo called', dbg_id)) + events.append(('foo token', self.dbg.AddDestroyCallback(foo))) + + def remove_bar(dbg_id): + # Need nonlocal to modify closure variable. + nonlocal events + events.append(('remove_bar called', dbg_id)) + events.append(('remove bar ret', self.dbg.RemoveDestroyCallback(bar_token))) + + # Setup + events.append(('add_foo token', self.dbg.AddDestroyCallback(add_foo))) + bar_token = self.dbg.AddDestroyCallback(bar) + events.append(('bar token', bar_token)) + events.append(('remove_bar token', self.dbg.AddDestroyCallback(remove_bar))) + # Destroy + self.dbg.Destroy(self.dbg) + + self.assertEqual(events, [ + # Setup + ('add_foo token', 0), # add_foo should be added + ('bar token', 1), # bar should be added + ('remove_bar token', 2), # remove_bar should be added + # Destroy + ('add_foo called', original_dbg_id), # add_foo should be called + ('foo token', 3), # foo should be added + ('bar called', original_dbg_id), # bar should be called + ('remove_bar called', original_dbg_id), # remove_bar should be called + ('remove bar ret', False), # remove_bar should fail, because it's already invoked and removed + ('foo called', original_dbg_id), # foo should be called + ]) -- GitLab From 00d7e67f8352308288db483f03294460a38a3773 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Mon, 20 May 2024 17:59:27 -0500 Subject: [PATCH 140/793] [libc] Fix constant address space on global clock Summary: I did this wrong in the first version, because `extern "C"` doesn't imply it's extern when used directly. --- libc/src/time/gpu/time_utils.cpp | 3 +-- libc/src/time/gpu/time_utils.h | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libc/src/time/gpu/time_utils.cpp b/libc/src/time/gpu/time_utils.cpp index 67fe5b4861ac..1a674b2fdca2 100644 --- a/libc/src/time/gpu/time_utils.cpp +++ b/libc/src/time/gpu/time_utils.cpp @@ -15,8 +15,7 @@ namespace LIBC_NAMESPACE { // insufficient. // TODO: Once we have another use-case for this we should put it in a common // device environment struct. -extern "C" [[gnu::visibility("protected")]] uint64_t __llvm_libc_clock_freq = - clock_freq; +gpu::Constant __llvm_libc_clock_freq = clock_freq; #endif } // namespace LIBC_NAMESPACE diff --git a/libc/src/time/gpu/time_utils.h b/libc/src/time/gpu/time_utils.h index da713886b643..77eeb896f6c3 100644 --- a/libc/src/time/gpu/time_utils.h +++ b/libc/src/time/gpu/time_utils.h @@ -23,7 +23,10 @@ constexpr uint64_t clock_freq = 100000000UL; // We provide an externally visible symbol such that the runtime can set // this to the correct value. -extern "C" [[gnu::visibility("protected")]] uint64_t __llvm_libc_clock_freq; +extern "C" { +[[gnu::visibility("protected")]] +extern gpu::Constant __llvm_libc_clock_freq; +} #define GPU_CLOCKS_PER_SEC static_cast(__llvm_libc_clock_freq) #elif defined(LIBC_TARGET_ARCH_IS_NVPTX) -- GitLab From 93540455669ab9ad55bd7e24a42a305194a109af Mon Sep 17 00:00:00 2001 From: Slava Zakharin Date: Mon, 20 May 2024 16:16:07 -0700 Subject: [PATCH 141/793] [NFC][flang][runtime] Avoid recursion in EditCharacterOutput and EditLogicalOutput. (#92806) --- flang/runtime/edit-output.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/flang/runtime/edit-output.cpp b/flang/runtime/edit-output.cpp index 13ab91fc56ea..6b24c5648318 100644 --- a/flang/runtime/edit-output.cpp +++ b/flang/runtime/edit-output.cpp @@ -832,8 +832,11 @@ RT_API_ATTRS bool EditLogicalOutput( reinterpret_cast(&truth), sizeof truth); case 'A': { // legacy extension int truthBits{truth}; - return EditCharacterOutput( - io, edit, reinterpret_cast(&truthBits), sizeof truthBits); + int len{sizeof truthBits}; + int width{edit.width.value_or(len)}; + return EmitRepeated(io, ' ', std::max(0, width - len)) && + EmitEncoded( + io, reinterpret_cast(&truthBits), std::min(width, len)); } default: io.GetIoErrorHandler().SignalError(IostatErrorInFormat, -- GitLab From bccac125e196bd5afeeb2fef93cf501f4b9f7f83 Mon Sep 17 00:00:00 2001 From: Slava Zakharin Date: Mon, 20 May 2024 16:16:26 -0700 Subject: [PATCH 142/793] [flang][runtime] Added io-api-minimal.cpp to the offload build. (#92807) --- flang/runtime/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/flang/runtime/CMakeLists.txt b/flang/runtime/CMakeLists.txt index 4f7627eac81f..4c2afd0abe90 100644 --- a/flang/runtime/CMakeLists.txt +++ b/flang/runtime/CMakeLists.txt @@ -199,6 +199,7 @@ set(supported_files inquiry.cpp internal-unit.cpp io-api.cpp + io-api-minimal.cpp io-error.cpp io-stmt.cpp iostat.cpp -- GitLab From 888e087b09dbd658a03f27c475ada50d37323987 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 20 May 2024 16:17:19 -0700 Subject: [PATCH 143/793] [RISCV] Remove unused function declaration. NFC --- llvm/lib/Target/RISCV/RISCVISelLowering.h | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h index 1efc54566b4b..e8e7017cf8d1 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -959,7 +959,6 @@ private: SDValue lowerFixedLengthVectorSelectToRVV(SDValue Op, SelectionDAG &DAG) const; SDValue lowerToScalableOp(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerUnsignedAvgFloor(SDValue Op, SelectionDAG &DAG) const; SDValue LowerIS_FPCLASS(SDValue Op, SelectionDAG &DAG) const; SDValue lowerVPOp(SDValue Op, SelectionDAG &DAG) const; SDValue lowerLogicVPOp(SDValue Op, SelectionDAG &DAG) const; -- GitLab From bb627b0a0c05e0bb04ae7f984b8e7fcd84906061 Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Mon, 20 May 2024 16:55:11 -0700 Subject: [PATCH 144/793] [BOLT] Ignore special symbols as function aliases in updateELFSymbolTable Exempt special symbols (hot text/data and _end symbol) from normal handling. We only need to set their value and make them absolute. If these symbols are handled as normal symbols and if they alias functions we may create non-sensical symbols, e.g. __hot_start.cold. Test Plan: updated hot-end-symbol.s Reviewers: maksfb, rafaelauler, ayermolo, dcci Reviewed By: dcci, maksfb Pull Request: https://github.com/llvm/llvm-project/pull/92713 --- bolt/lib/Rewrite/RewriteInstance.cpp | 62 +++++++++++++++----------- bolt/test/runtime/X86/hot-end-symbol.s | 3 +- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 85b39176754b..6e1021a6df22 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -4808,6 +4808,40 @@ void RewriteInstance::updateELFSymbolTable( // Create a new symbol based on the existing symbol. ELFSymTy NewSymbol = Symbol; + // Handle special symbols based on their name. + Expected SymbolName = Symbol.getName(StringSection); + assert(SymbolName && "cannot get symbol name"); + + auto updateSymbolValue = [&](const StringRef Name, + std::optional Value = std::nullopt) { + NewSymbol.st_value = Value ? *Value : getNewValueForSymbol(Name); + NewSymbol.st_shndx = ELF::SHN_ABS; + BC->outs() << "BOLT-INFO: setting " << Name << " to 0x" + << Twine::utohexstr(NewSymbol.st_value) << '\n'; + }; + + if (*SymbolName == "__hot_start" || *SymbolName == "__hot_end") { + if (opts::HotText) { + updateSymbolValue(*SymbolName); + ++NumHotTextSymsUpdated; + } + goto registerSymbol; + } + + if (*SymbolName == "__hot_data_start" || *SymbolName == "__hot_data_end") { + if (opts::HotData) { + updateSymbolValue(*SymbolName); + ++NumHotDataSymsUpdated; + } + goto registerSymbol; + } + + if (*SymbolName == "_end") { + if (NextAvailableAddress > Symbol.st_value) + updateSymbolValue(*SymbolName, NextAvailableAddress); + goto registerSymbol; + } + if (Function) { // If the symbol matched a function that was not emitted, update the // corresponding section index but otherwise leave it unchanged. @@ -4904,33 +4938,7 @@ void RewriteInstance::updateELFSymbolTable( } } - // Handle special symbols based on their name. - Expected SymbolName = Symbol.getName(StringSection); - assert(SymbolName && "cannot get symbol name"); - - auto updateSymbolValue = [&](const StringRef Name, - std::optional Value = std::nullopt) { - NewSymbol.st_value = Value ? *Value : getNewValueForSymbol(Name); - NewSymbol.st_shndx = ELF::SHN_ABS; - BC->outs() << "BOLT-INFO: setting " << Name << " to 0x" - << Twine::utohexstr(NewSymbol.st_value) << '\n'; - }; - - if (opts::HotText && - (*SymbolName == "__hot_start" || *SymbolName == "__hot_end")) { - updateSymbolValue(*SymbolName); - ++NumHotTextSymsUpdated; - } - - if (opts::HotData && (*SymbolName == "__hot_data_start" || - *SymbolName == "__hot_data_end")) { - updateSymbolValue(*SymbolName); - ++NumHotDataSymsUpdated; - } - - if (*SymbolName == "_end" && NextAvailableAddress > Symbol.st_value) - updateSymbolValue(*SymbolName, NextAvailableAddress); - + registerSymbol: if (IsDynSym) Write((&Symbol - cantFail(Obj.symbols(&SymTabSection)).begin()) * sizeof(ELFSymTy), diff --git a/bolt/test/runtime/X86/hot-end-symbol.s b/bolt/test/runtime/X86/hot-end-symbol.s index e6d83d77167a..6ae771cead75 100755 --- a/bolt/test/runtime/X86/hot-end-symbol.s +++ b/bolt/test/runtime/X86/hot-end-symbol.s @@ -12,6 +12,7 @@ # RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-q # RUN: llvm-bolt %t.exe --relocs=1 --hot-text --reorder-functions=hfsort \ +# RUN: --split-functions --split-strategy=all \ # RUN: --data %t.fdata -o %t.out | FileCheck %s # RUN: %t.out 1 @@ -30,12 +31,12 @@ # CHECK-OUTPUT: __hot_start # CHECK-OUTPUT-NEXT: main # CHECK-OUTPUT-NEXT: __hot_end +# CHECK-OUTPUT-NOT: __hot_start.cold .text .globl main .type main, %function .globl __hot_start - .type __hot_start, %object .p2align 4 main: __hot_start: -- GitLab From 7064e4b1633811da984261fdc585ba4438efe827 Mon Sep 17 00:00:00 2001 From: Min-Yih Hsu Date: Mon, 20 May 2024 17:00:38 -0700 Subject: [PATCH 145/793] [RISCV] Split and rename WriteVISlideX into WriteVSlideUpX and WriteVSlideDownX (#92605) Some processors might have different latencies and/or rthroughput for slide up and down operations on integer vectors, yet there is only a single SchedWrite for both of them at this moment. This patch splits this SchedWrite into two as well as drop the "I" before "Slide" since such information is redundant. We also do the same renaming on `WriteVISlideI`. Note that we only split the X variant (i.e. using a register value for index offset) for now. This is effectively NFC. --- llvm/lib/Target/RISCV/RISCVInstrInfoV.td | 13 ++++++++----- llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td | 12 +++++++----- llvm/lib/Target/RISCV/RISCVSchedSiFive7.td | 9 +++++---- llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td | 8 +++++--- llvm/lib/Target/RISCV/RISCVScheduleV.td | 10 ++++++---- 5 files changed, 31 insertions(+), 21 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoV.td index e68fb42ece9f..0bbf71519953 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoV.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoV.td @@ -975,11 +975,14 @@ multiclass VNCLP_IV_V_X_I funct6> { SchedUnaryMC<"WriteVNClipI", "ReadVNClipV">; } -multiclass VSLD_IV_X_I funct6> { +multiclass VSLD_IV_X_I funct6, bit slidesUp> { + // Note: In the future, if VISlideI is also split into VSlideUpI and + // VSlideDownI, it'll probably better to use two separate multiclasses. + defvar WriteSlideX = !if(slidesUp, "WriteVSlideUpX", "WriteVSlideDownX"); def X : VALUVX, - SchedBinaryMC<"WriteVISlideX", "ReadVISlideV", "ReadVISlideX">; + SchedBinaryMC; def I : VALUVI, - SchedUnaryMC<"WriteVISlideI", "ReadVISlideV">; + SchedUnaryMC<"WriteVSlideI", "ReadVISlideV">; } multiclass VSLD1_MV_X funct6> { @@ -1658,10 +1661,10 @@ def VFMV_S_F : RVInstV2<0b010000, 0b00000, OPFVF, (outs VR:$vd_wb), let Predicates = [HasVInstructions] in { // Vector Slide Instructions let Constraints = "@earlyclobber $vd", RVVConstraint = SlideUp in { -defm VSLIDEUP_V : VSLD_IV_X_I<"vslideup", 0b001110>; +defm VSLIDEUP_V : VSLD_IV_X_I<"vslideup", 0b001110, /*slidesUp=*/true>; defm VSLIDE1UP_V : VSLD1_MV_X<"vslide1up", 0b001110>; } // Constraints = "@earlyclobber $vd", RVVConstraint = SlideUp -defm VSLIDEDOWN_V : VSLD_IV_X_I<"vslidedown", 0b001111>; +defm VSLIDEDOWN_V : VSLD_IV_X_I<"vslidedown", 0b001111, /*slidesUp=*/false>; defm VSLIDE1DOWN_V : VSLD1_MV_X<"vslide1down", 0b001111>; } // Predicates = [HasVInstructions] diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td index 317a6d7d4c52..8bf0f25d496a 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -3380,14 +3380,16 @@ multiclass VPseudoVMAC_VV_VF_AAXA_RM { } } -multiclass VPseudoVSLD_VX_VI { +multiclass VPseudoVSLD_VX_VI { + defvar WriteSlideX = !if(slidesUp, "WriteVSlideUpX", "WriteVSlideDownX"); foreach m = MxList in { defvar mx = m.MX; defm "" : VPseudoVSLDV_VX, - SchedTernary<"WriteVISlideX", "ReadVISlideV", "ReadVISlideV", + SchedTernary; defm "" : VPseudoVSLDV_VI, - SchedBinary<"WriteVISlideI", "ReadVISlideV", "ReadVISlideV", mx>; + SchedBinary<"WriteVSlideI", "ReadVISlideV", "ReadVISlideV", mx>; } } @@ -6861,8 +6863,8 @@ let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in { // 16.3. Vector Slide Instructions //===----------------------------------------------------------------------===// let Predicates = [HasVInstructions] in { - defm PseudoVSLIDEUP : VPseudoVSLD_VX_VI; - defm PseudoVSLIDEDOWN : VPseudoVSLD_VX_VI; + defm PseudoVSLIDEUP : VPseudoVSLD_VX_VI; + defm PseudoVSLIDEDOWN : VPseudoVSLD_VX_VI; defm PseudoVSLIDE1UP : VPseudoVSLD1_VX<"@earlyclobber $rd">; defm PseudoVSLIDE1DOWN : VPseudoVSLD1_VX; } // Predicates = [HasVInstructions] diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td index e67da839bdb8..83fb75727bbe 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td @@ -937,10 +937,11 @@ foreach mx = SchedMxList in { defvar Cycles = SiFive7GetCyclesDefault.c; defvar IsWorstCase = SiFive7IsWorstCaseMX.c; let Latency = 4, AcquireAtCycles = [0, 1], ReleaseAtCycles = [1, !add(1, Cycles)] in { - defm "" : LMULWriteResMX<"WriteVISlideX", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVISlideI", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVISlide1X", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; - defm "" : LMULWriteResMX<"WriteVFSlide1F", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSlideUpX", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSlideDownX", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSlideI", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVISlide1X", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFSlide1F", [SiFive7VCQ, SiFive7VA], mx, IsWorstCase>; } } diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td index 6ba299385f07..07d72b61862d 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td @@ -669,7 +669,7 @@ foreach mx = SchedMxList in { defvar LMulLat = SiFiveP600GetLMulCycles.c; defvar IsWorstCase = SiFiveP600IsWorstCaseMX.c; let Latency = 2, ReleaseAtCycles = [LMulLat] in { - defm "" : LMULWriteResMX<"WriteVISlideI", [SiFiveP600VEXQ0], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSlideI", [SiFiveP600VEXQ0], mx, IsWorstCase>; } let Latency = 1, ReleaseAtCycles = [LMulLat] in { defm "" : LMULWriteResMX<"WriteVISlide1X", [SiFiveP600VEXQ0], mx, IsWorstCase>; @@ -679,7 +679,8 @@ foreach mx = SchedMxList in { foreach mx = ["MF8", "MF4", "MF2", "M1"] in { defvar IsWorstCase = SiFiveP600IsWorstCaseMX.c; let Latency = 2, ReleaseAtCycles = [1] in { - defm "" : LMULWriteResMX<"WriteVISlideX", [SiFiveP600VEXQ0], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSlideUpX", [SiFiveP600VEXQ0], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSlideDownX", [SiFiveP600VEXQ0], mx, IsWorstCase>; } } @@ -688,7 +689,8 @@ foreach mx = ["M8", "M4", "M2"] in { defvar LMulLat = SiFiveP600GetLMulCycles.c; defvar IsWorstCase = SiFiveP600IsWorstCaseMX.c; let Latency = !add(4, LMulLat), ReleaseAtCycles = [LMulLat] in { - defm "" : LMULWriteResMX<"WriteVISlideX", [SiFiveP600VEXQ1], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSlideUpX", [SiFiveP600VEXQ1], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSlideDownX", [SiFiveP600VEXQ1], mx, IsWorstCase>; } } diff --git a/llvm/lib/Target/RISCV/RISCVScheduleV.td b/llvm/lib/Target/RISCV/RISCVScheduleV.td index 5be06d4c3f7e..e4524185991e 100644 --- a/llvm/lib/Target/RISCV/RISCVScheduleV.td +++ b/llvm/lib/Target/RISCV/RISCVScheduleV.td @@ -514,8 +514,9 @@ def WriteVMovXS : SchedWrite; def WriteVMovSF : SchedWrite; def WriteVMovFS : SchedWrite; // 16.3. Vector Slide Instructions -defm "" : LMULSchedWrites<"WriteVISlideX">; -defm "" : LMULSchedWrites<"WriteVISlideI">; +defm "" : LMULSchedWrites<"WriteVSlideUpX">; +defm "" : LMULSchedWrites<"WriteVSlideDownX">; +defm "" : LMULSchedWrites<"WriteVSlideI">; defm "" : LMULSchedWrites<"WriteVISlide1X">; defm "" : LMULSchedWrites<"WriteVFSlide1F">; // 16.4. Vector Register Gather Instructions @@ -949,8 +950,9 @@ def : WriteRes; def : WriteRes; def : WriteRes; def : WriteRes; -defm "" : LMULWriteRes<"WriteVISlideX", []>; -defm "" : LMULWriteRes<"WriteVISlideI", []>; +defm "" : LMULWriteRes<"WriteVSlideUpX", []>; +defm "" : LMULWriteRes<"WriteVSlideDownX", []>; +defm "" : LMULWriteRes<"WriteVSlideI", []>; defm "" : LMULWriteRes<"WriteVISlide1X", []>; defm "" : LMULWriteRes<"WriteVFSlide1F", []>; defm "" : LMULSEWWriteRes<"WriteVRGatherVV", []>; -- GitLab From 3fa6b3bbdb0f9de18def8596d1f7fcec2ef77b5e Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 20 May 2024 17:15:52 -0700 Subject: [PATCH 146/793] [llvm-profdata] Fix some style and clang-tidy issues Fix #92761 Fix #92762 --- .../llvm/ProfileData/SampleProfReader.h | 10 ++++----- llvm/lib/ProfileData/SampleProfReader.cpp | 8 +++---- llvm/tools/llvm-profdata/llvm-profdata.cpp | 21 +++++++++---------- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/llvm/include/llvm/ProfileData/SampleProfReader.h b/llvm/include/llvm/ProfileData/SampleProfReader.h index 9e8f543909cd..d7c70064ca42 100644 --- a/llvm/include/llvm/ProfileData/SampleProfReader.h +++ b/llvm/include/llvm/ProfileData/SampleProfReader.h @@ -274,8 +274,8 @@ public: /// Create a remapper from the given remapping file. The remapper will /// be used for profile read in by Reader. static ErrorOr> - create(const std::string Filename, vfs::FileSystem &FS, - SampleProfileReader &Reader, LLVMContext &C); + create(StringRef Filename, vfs::FileSystem &FS, SampleProfileReader &Reader, + LLVMContext &C); /// Create a remapper from the given Buffer. The remapper will /// be used for profile read in by Reader. @@ -436,9 +436,9 @@ public: /// Create a remapper underlying if RemapFilename is not empty. /// Parameter P specifies the FSDiscriminatorPass. static ErrorOr> - create(const std::string Filename, LLVMContext &C, vfs::FileSystem &FS, + create(StringRef Filename, LLVMContext &C, vfs::FileSystem &FS, FSDiscriminatorPass P = FSDiscriminatorPass::Base, - const std::string RemapFilename = ""); + StringRef RemapFilename = ""); /// Create a sample profile reader from the supplied memory buffer. /// Create a remapper underlying if RemapFilename is not empty. @@ -446,7 +446,7 @@ public: static ErrorOr> create(std::unique_ptr &B, LLVMContext &C, vfs::FileSystem &FS, FSDiscriminatorPass P = FSDiscriminatorPass::Base, - const std::string RemapFilename = ""); + StringRef RemapFilename = ""); /// Return the profile summary. ProfileSummary &getSummary() const { return *(Summary.get()); } diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp index f91a0e6177ea..a4b2d0668a5a 100644 --- a/llvm/lib/ProfileData/SampleProfReader.cpp +++ b/llvm/lib/ProfileData/SampleProfReader.cpp @@ -1822,9 +1822,9 @@ setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS) { /// /// \returns an error code indicating the status of the created reader. ErrorOr> -SampleProfileReader::create(const std::string Filename, LLVMContext &C, +SampleProfileReader::create(StringRef Filename, LLVMContext &C, vfs::FileSystem &FS, FSDiscriminatorPass P, - const std::string RemapFilename) { + StringRef RemapFilename) { auto BufferOrError = setupMemoryBuffer(Filename, FS); if (std::error_code EC = BufferOrError.getError()) return EC; @@ -1842,7 +1842,7 @@ SampleProfileReader::create(const std::string Filename, LLVMContext &C, /// /// \returns an error code indicating the status of the created reader. ErrorOr> -SampleProfileReaderItaniumRemapper::create(const std::string Filename, +SampleProfileReaderItaniumRemapper::create(StringRef Filename, vfs::FileSystem &FS, SampleProfileReader &Reader, LLVMContext &C) { @@ -1895,7 +1895,7 @@ SampleProfileReaderItaniumRemapper::create(std::unique_ptr &B, ErrorOr> SampleProfileReader::create(std::unique_ptr &B, LLVMContext &C, vfs::FileSystem &FS, FSDiscriminatorPass P, - const std::string RemapFilename) { + StringRef RemapFilename) { std::unique_ptr Reader; if (SampleProfileReaderRawBinary::hasFormat(*B)) Reader.reset(new SampleProfileReaderRawBinary(std::move(B), C)); diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp index 4126b55576dd..693af066bc0f 100644 --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -75,7 +75,6 @@ cl::SubCommand MergeSubcommand( namespace { enum ProfileKinds { instr, sample, memory }; enum FailureMode { warnOnly, failIfAnyAreInvalid, failIfAllAreInvalid }; -} // namespace enum ProfileFormat { PF_None = 0, @@ -87,6 +86,7 @@ enum ProfileFormat { }; enum class ShowFormat { Text, Json, Yaml }; +} // namespace // Common options. cl::opt OutputFilename("output", cl::value_desc("output"), @@ -443,8 +443,7 @@ cl::opt ShowProfileVersion("profile-version", cl::init(false), // multiple static functions map to the same name. const std::string DuplicateNameStr = "----"; -static void warn(Twine Message, std::string Whence = "", - std::string Hint = "") { +static void warn(Twine Message, StringRef Whence = "", StringRef Hint = "") { WithColor::warning(); if (!Whence.empty()) errs() << Whence << ": "; @@ -456,13 +455,13 @@ static void warn(Twine Message, std::string Whence = "", static void warn(Error E, StringRef Whence = "") { if (E.isA()) { handleAllErrors(std::move(E), [&](const InstrProfError &IPE) { - warn(IPE.message(), std::string(Whence), std::string("")); + warn(IPE.message(), Whence); }); } } -static void exitWithError(Twine Message, std::string Whence = "", - std::string Hint = "") { +static void exitWithError(Twine Message, StringRef Whence = "", + StringRef Hint = "") { WithColor::error(); if (!Whence.empty()) errs() << Whence << ": "; @@ -481,16 +480,16 @@ static void exitWithError(Error E, StringRef Whence = "") { // Hint in case user missed specifying the profile type. Hint = "Perhaps you forgot to use the --sample or --memory option?"; } - exitWithError(IPE.message(), std::string(Whence), std::string(Hint)); + exitWithError(IPE.message(), Whence, Hint); }); return; } - exitWithError(toString(std::move(E)), std::string(Whence)); + exitWithError(toString(std::move(E)), Whence); } static void exitWithErrorCode(std::error_code EC, StringRef Whence = "") { - exitWithError(EC.message(), std::string(Whence)); + exitWithError(EC.message(), Whence); } static void warnOrExitGivenError(FailureMode FailMode, std::error_code EC, @@ -498,7 +497,7 @@ static void warnOrExitGivenError(FailureMode FailMode, std::error_code EC, if (FailMode == failIfAnyAreInvalid) exitWithErrorCode(EC, Whence); else - warn(EC.message(), std::string(Whence)); + warn(EC.message(), Whence); } static void handleMergeWriterError(Error E, StringRef WhenceFile = "", @@ -1585,7 +1584,7 @@ static void mergeSampleProfile(const WeightedFileVector &Inputs, // If OutputSizeLimit is 0 (default), it is the same as write(). if (std::error_code EC = Writer->writeWithSizeLimit(ProfileMap, OutputSizeLimit)) - exitWithErrorCode(std::move(EC)); + exitWithErrorCode(EC); } static WeightedFile parseWeightedFile(const StringRef &WeightedFilename) { -- GitLab From 45968da95d8959a7c4ca7d56f501bb12de413fcc Mon Sep 17 00:00:00 2001 From: Shilei Tian Date: Mon, 20 May 2024 21:32:02 -0400 Subject: [PATCH 147/793] [AMDGPU] Fix an issue that wrong index is used in calculation of byte provider when the op is extract_vector_elt (#91697) Fixes: SWDEV-460097 --- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 6 +- .../match-perm-extract-vector-elt-bug.ll | 109 ++++++++++++++++++ llvm/test/CodeGen/AMDGPU/permute_i8.ll | 25 ++-- 3 files changed, 125 insertions(+), 15 deletions(-) create mode 100644 llvm/test/CodeGen/AMDGPU/match-perm-extract-vector-elt-bug.ll diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index d7b6941fcf81..42e1c1ce764c 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -12074,11 +12074,9 @@ calculateByteProvider(const SDValue &Op, unsigned Index, unsigned Depth, return std::nullopt; auto VecIdx = IdxOp->getZExtValue(); auto ScalarSize = Op.getScalarValueSizeInBits(); - if (ScalarSize != 32) { + if (ScalarSize < 32) Index = ScalarSize == 8 ? VecIdx : VecIdx * 2 + Index; - } - - return calculateSrcByte(ScalarSize == 32 ? Op : Op.getOperand(0), + return calculateSrcByte(ScalarSize >= 32 ? Op : Op.getOperand(0), StartingIndex, Index); } diff --git a/llvm/test/CodeGen/AMDGPU/match-perm-extract-vector-elt-bug.ll b/llvm/test/CodeGen/AMDGPU/match-perm-extract-vector-elt-bug.ll new file mode 100644 index 000000000000..c7a831185b83 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/match-perm-extract-vector-elt-bug.ll @@ -0,0 +1,109 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 %s -o - | FileCheck -check-prefix=GFX9 %s +; RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1030 %s -o - | FileCheck -check-prefix=GFX10 %s +; RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 %s -o - | FileCheck -check-prefix=GFX11 %s + +define amdgpu_kernel void @test(ptr addrspace(1) %src, ptr addrspace(1) %dst) { +; GFX9-LABEL: test: +; GFX9: ; %bb.0: ; %entry +; GFX9-NEXT: s_load_dword s7, s[4:5], 0x1c +; GFX9-NEXT: s_load_dword s8, s[4:5], 0x38 +; GFX9-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_and_b32 s4, s7, 0xffff +; GFX9-NEXT: s_mul_i32 s6, s6, s4 +; GFX9-NEXT: s_add_i32 s8, s8, s6 +; GFX9-NEXT: v_add_u32_e32 v0, s8, v0 +; GFX9-NEXT: v_ashrrev_i32_e32 v1, 31, v0 +; GFX9-NEXT: v_lshlrev_b64 v[4:5], 4, v[0:1] +; GFX9-NEXT: v_mov_b32_e32 v1, s1 +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, s0, v4 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v5, vcc +; GFX9-NEXT: global_load_dwordx4 v[0:3], v[0:1], off +; GFX9-NEXT: v_mov_b32_e32 v6, s3 +; GFX9-NEXT: v_add_co_u32_e32 v4, vcc, s2, v4 +; GFX9-NEXT: v_addc_co_u32_e32 v5, vcc, v6, v5, vcc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_not_b32_e32 v3, v3 +; GFX9-NEXT: v_not_b32_e32 v2, v2 +; GFX9-NEXT: v_not_b32_e32 v1, v1 +; GFX9-NEXT: v_not_b32_e32 v0, v0 +; GFX9-NEXT: global_store_dwordx4 v[4:5], v[0:3], off +; GFX9-NEXT: s_endpgm +; +; GFX10-LABEL: test: +; GFX10: ; %bb.0: ; %entry +; GFX10-NEXT: s_clause 0x2 +; GFX10-NEXT: s_load_dword s7, s[4:5], 0x1c +; GFX10-NEXT: s_load_dword s8, s[4:5], 0x38 +; GFX10-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x0 +; GFX10-NEXT: s_waitcnt lgkmcnt(0) +; GFX10-NEXT: s_and_b32 s4, s7, 0xffff +; GFX10-NEXT: s_mul_i32 s6, s6, s4 +; GFX10-NEXT: v_add3_u32 v0, s8, s6, v0 +; GFX10-NEXT: v_ashrrev_i32_e32 v1, 31, v0 +; GFX10-NEXT: v_lshlrev_b64 v[4:5], 4, v[0:1] +; GFX10-NEXT: v_add_co_u32 v0, vcc_lo, s0, v4 +; GFX10-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, s1, v5, vcc_lo +; GFX10-NEXT: v_add_co_u32 v4, vcc_lo, s2, v4 +; GFX10-NEXT: v_add_co_ci_u32_e32 v5, vcc_lo, s3, v5, vcc_lo +; GFX10-NEXT: global_load_dwordx4 v[0:3], v[0:1], off +; GFX10-NEXT: s_waitcnt vmcnt(0) +; GFX10-NEXT: v_not_b32_e32 v3, v3 +; GFX10-NEXT: v_not_b32_e32 v2, v2 +; GFX10-NEXT: v_not_b32_e32 v1, v1 +; GFX10-NEXT: v_not_b32_e32 v0, v0 +; GFX10-NEXT: global_store_dwordx4 v[4:5], v[0:3], off +; GFX10-NEXT: s_endpgm +; +; GFX11-LABEL: test: +; GFX11: ; %bb.0: ; %entry +; GFX11-NEXT: s_clause 0x2 +; GFX11-NEXT: s_load_b32 s4, s[0:1], 0x1c +; GFX11-NEXT: s_load_b32 s5, s[0:1], 0x38 +; GFX11-NEXT: s_load_b128 s[0:3], s[0:1], 0x0 +; GFX11-NEXT: s_waitcnt lgkmcnt(0) +; GFX11-NEXT: s_and_b32 s4, s4, 0xffff +; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1) +; GFX11-NEXT: s_mul_i32 s15, s15, s4 +; GFX11-NEXT: v_add3_u32 v0, s5, s15, v0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX11-NEXT: v_ashrrev_i32_e32 v1, 31, v0 +; GFX11-NEXT: v_lshlrev_b64 v[4:5], 4, v[0:1] +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_2) +; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, s0, v4 +; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, s1, v5, vcc_lo +; GFX11-NEXT: v_add_co_u32 v4, vcc_lo, s2, v4 +; GFX11-NEXT: v_add_co_ci_u32_e32 v5, vcc_lo, s3, v5, vcc_lo +; GFX11-NEXT: global_load_b128 v[0:3], v[0:1], off +; GFX11-NEXT: s_waitcnt vmcnt(0) +; GFX11-NEXT: v_not_b32_e32 v3, v3 +; GFX11-NEXT: v_not_b32_e32 v2, v2 +; GFX11-NEXT: v_not_b32_e32 v1, v1 +; GFX11-NEXT: v_not_b32_e32 v0, v0 +; GFX11-NEXT: global_store_b128 v[4:5], v[0:3], off +; GFX11-NEXT: s_nop 0 +; GFX11-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) +; GFX11-NEXT: s_endpgm +entry: + %implicitarg.ptr = tail call ptr addrspace(4) @llvm.amdgcn.implicitarg.ptr() + %arg.1.ptr = getelementptr inbounds i8, ptr addrspace(4) %implicitarg.ptr, i64 40 + %arg.1 = load i64, ptr addrspace(4) %arg.1.ptr, align 8 + %workgroup.id.x = tail call i32 @llvm.amdgcn.workgroup.id.x() + %arg.2.ptr = getelementptr inbounds i8, ptr addrspace(4) %implicitarg.ptr, i64 12 + %arg.2 = load i16, ptr addrspace(4) %arg.2.ptr, align 4 + %arg.2.ext = zext i16 %arg.2 to i32 + %mul = mul i32 %workgroup.id.x, %arg.2.ext + %workitem.id.x = tail call i32 @llvm.amdgcn.workitem.id.x() + %add = add i32 %mul, %workitem.id.x + %add.ext = zext i32 %add to i64 + %add.1 = add i64 %arg.1, %add.ext + %sext = shl i64 %add.1, 32 + %idxprom = ashr exact i64 %sext, 32 + %arrayidx = getelementptr inbounds <16 x i8>, ptr addrspace(1) %src, i64 %idxprom + %arrayval = load <16 x i8>, ptr addrspace(1) %arrayidx, align 16 + %not = xor <16 x i8> %arrayval, + %arrayidx2 = getelementptr inbounds <16 x i8>, ptr addrspace(1) %dst, i64 %idxprom + store <16 x i8> %not, ptr addrspace(1) %arrayidx2, align 16 + ret void +} diff --git a/llvm/test/CodeGen/AMDGPU/permute_i8.ll b/llvm/test/CodeGen/AMDGPU/permute_i8.ll index 8ac332197215..7ca9ae359a49 100644 --- a/llvm/test/CodeGen/AMDGPU/permute_i8.ll +++ b/llvm/test/CodeGen/AMDGPU/permute_i8.ll @@ -3816,13 +3816,15 @@ define hidden void @extract_v13i64(ptr addrspace(1) %in0, ptr addrspace(1) %in1, ; GFX10-LABEL: extract_v13i64: ; GFX10: ; %bb.0: ; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX10-NEXT: s_clause 0x1 -; GFX10-NEXT: global_load_dwordx4 v[8:11], v[0:1], off -; GFX10-NEXT: global_load_dwordx4 v[12:15], v[0:1], off offset:16 +; GFX10-NEXT: s_clause 0x2 +; GFX10-NEXT: global_load_dwordx4 v[8:11], v[0:1], off offset:48 +; GFX10-NEXT: global_load_dwordx4 v[11:14], v[0:1], off +; GFX10-NEXT: global_load_dwordx4 v[14:17], v[0:1], off offset:64 +; GFX10-NEXT: ; kill: killed $vgpr0 killed $vgpr1 ; GFX10-NEXT: s_waitcnt vmcnt(1) -; GFX10-NEXT: v_perm_b32 v0, v9, v8, 0x3020504 +; GFX10-NEXT: v_perm_b32 v0, v12, v13, 0x1000504 ; GFX10-NEXT: s_waitcnt vmcnt(0) -; GFX10-NEXT: v_perm_b32 v1, v11, v12, 0x1000706 +; GFX10-NEXT: v_perm_b32 v1, v10, v14, 0x1000504 ; GFX10-NEXT: global_store_dword v[4:5], v0, off ; GFX10-NEXT: global_store_dword v[6:7], v1, off ; GFX10-NEXT: s_setpc_b64 s[30:31] @@ -3830,14 +3832,15 @@ define hidden void @extract_v13i64(ptr addrspace(1) %in0, ptr addrspace(1) %in1, ; GFX9-LABEL: extract_v13i64: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX9-NEXT: global_load_dwordx4 v[8:11], v[0:1], off -; GFX9-NEXT: global_load_dwordx4 v[12:15], v[0:1], off offset:16 -; GFX9-NEXT: s_mov_b32 s4, 0x3020504 -; GFX9-NEXT: s_mov_b32 s5, 0x1000706 +; GFX9-NEXT: global_load_dwordx4 v[8:11], v[0:1], off offset:48 +; GFX9-NEXT: global_load_dwordx4 v[11:14], v[0:1], off +; GFX9-NEXT: global_load_dwordx4 v[14:17], v[0:1], off offset:64 +; GFX9-NEXT: s_mov_b32 s4, 0x1000504 +; GFX9-NEXT: ; kill: killed $vgpr0 killed $vgpr1 ; GFX9-NEXT: s_waitcnt vmcnt(1) -; GFX9-NEXT: v_perm_b32 v0, v9, v8, s4 +; GFX9-NEXT: v_perm_b32 v0, v12, v13, s4 ; GFX9-NEXT: s_waitcnt vmcnt(0) -; GFX9-NEXT: v_perm_b32 v1, v11, v12, s5 +; GFX9-NEXT: v_perm_b32 v1, v10, v14, s4 ; GFX9-NEXT: global_store_dword v[4:5], v0, off ; GFX9-NEXT: global_store_dword v[6:7], v1, off ; GFX9-NEXT: s_waitcnt vmcnt(0) -- GitLab From d1aca0ae2e0c52298966e35e4312e21045d4c6e4 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Mon, 20 May 2024 18:43:13 -0700 Subject: [PATCH 148/793] [WebAssembly] Define __WASM_EXCEPTIONS__ for -fwasm-exceptions (#92604) When using other specific exception options in Clang, such as `-fseh-exceptions` or `-fsjlj-exceptions`, Clang defines a corresponding preprocessor such as `-D__USING_SJLJ_EXCEPTIONS__`. Emscripten does that in our own build system: https://github.com/emscripten-core/emscripten/blob/7dcd7f40749918e141dc33397d2f4311dd80637a/tools/system_libs.py#L1577-L1578 But to make Wasm EH usable in non-Emscripten toolchain, this has to be defined somewhere else. This PR makes Wasm EH consistent with other exception scheme by letting it defined by Clang depending on the exception option. We have been using `__USING_WASM_EXCEPTIONS__` in our current library code, but this changes it to `__WASM_EXCEPTIONS__` for its conciseness, and I will update other parts of LLVM as follow-ups. This does not break anything currently working, because we have not been defining anything in Clang so far. --- clang/lib/Frontend/InitPreprocessor.cpp | 2 ++ clang/test/CodeGenCXX/wasm-eh.cpp | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index c1d209466ffe..68760e00003e 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -1006,6 +1006,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI, else if (LangOpts.hasDWARFExceptions() && (TI.getTriple().isThumb() || TI.getTriple().isARM())) Builder.defineMacro("__ARM_DWARF_EH__"); + else if (LangOpts.hasWasmExceptions() && TI.getTriple().isWasm()) + Builder.defineMacro("__WASM_EXCEPTIONS__"); if (LangOpts.Deprecated) Builder.defineMacro("__DEPRECATED"); diff --git a/clang/test/CodeGenCXX/wasm-eh.cpp b/clang/test/CodeGenCXX/wasm-eh.cpp index 1b17498ba9ce..9dc15633bfed 100644 --- a/clang/test/CodeGenCXX/wasm-eh.cpp +++ b/clang/test/CodeGenCXX/wasm-eh.cpp @@ -1,4 +1,8 @@ // REQUIRES: webassembly-registered-target + +// RUN: %clang -E -dM %s -target wasm32-unknown-unknown -fwasm-exceptions | FileCheck %s -check-prefix PREPROCESSOR +// PREPROCESSOR: #define __WASM_EXCEPTIONS__ 1 + // RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -mllvm -wasm-enable-eh -exception-model=wasm -target-feature +exception-handling -emit-llvm -o - -std=c++11 | FileCheck %s // RUN: %clang_cc1 %s -triple wasm64-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -mllvm -wasm-enable-eh -exception-model=wasm -target-feature +exception-handling -emit-llvm -o - -std=c++11 | FileCheck %s -- GitLab From 8ce2045be0ce708af0bfce5dc14632fa15dc743a Mon Sep 17 00:00:00 2001 From: Younan Zhang Date: Tue, 21 May 2024 09:47:05 +0800 Subject: [PATCH 149/793] [Clang][Sema] Avoid pack expansion for expanded empty PackIndexingExprs (#92385) We previously doubled the id-expression expansion, even when the pack was expanded to empty. The previous condition for determining whether we should expand couldn't distinguish between cases where 'the expansion was previously postponed' and 'the expansion occurred but resulted in emptiness.' In the latter scenario, we crash because we have not been examining the current lambda's parent local instantiation scope since [D98068](https://reviews.llvm.org/D98068): Any Decls instantiated in the parent scope are not visible to the generic lambda, and thus any attempt of looking for instantiated Decls in the lambda is capped to the current Lambda's LIS. Fixes https://github.com/llvm/llvm-project/issues/92230 --- clang/include/clang/AST/ExprCXX.h | 19 +++++++++++++++---- clang/lib/AST/ExprCXX.cpp | 15 +++++++-------- clang/lib/Sema/SemaTemplateVariadic.cpp | 2 +- clang/lib/Sema/TreeTransform.h | 6 ++---- clang/lib/Serialization/ASTReaderStmt.cpp | 1 + clang/lib/Serialization/ASTWriterStmt.cpp | 2 +- clang/test/PCH/pack_indexing.cpp | 4 ++++ clang/test/SemaCXX/cxx2c-pack-indexing.cpp | 8 ++++++-- 8 files changed, 37 insertions(+), 20 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index fac65628ffed..dbf693611a7f 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -4377,15 +4377,21 @@ class PackIndexingExpr final // The pack being indexed, followed by the index Stmt *SubExprs[2]; - size_t TransformedExpressions; + // The size of the trailing expressions. + unsigned TransformedExpressions : 31; + + LLVM_PREFERRED_TYPE(bool) + unsigned ExpandedToEmptyPack : 1; PackIndexingExpr(QualType Type, SourceLocation EllipsisLoc, SourceLocation RSquareLoc, Expr *PackIdExpr, Expr *IndexExpr, - ArrayRef SubstitutedExprs = {}) + ArrayRef SubstitutedExprs = {}, + bool ExpandedToEmptyPack = false) : Expr(PackIndexingExprClass, Type, VK_LValue, OK_Ordinary), EllipsisLoc(EllipsisLoc), RSquareLoc(RSquareLoc), SubExprs{PackIdExpr, IndexExpr}, - TransformedExpressions(SubstitutedExprs.size()) { + TransformedExpressions(SubstitutedExprs.size()), + ExpandedToEmptyPack(ExpandedToEmptyPack) { auto *Exprs = getTrailingObjects(); std::uninitialized_copy(SubstitutedExprs.begin(), SubstitutedExprs.end(), @@ -4408,10 +4414,14 @@ public: SourceLocation EllipsisLoc, SourceLocation RSquareLoc, Expr *PackIdExpr, Expr *IndexExpr, std::optional Index, - ArrayRef SubstitutedExprs = {}); + ArrayRef SubstitutedExprs = {}, + bool ExpandedToEmptyPack = false); static PackIndexingExpr *CreateDeserialized(ASTContext &Context, unsigned NumTransformedExprs); + /// Determine if the expression was expanded to empty. + bool expandsToEmptyPack() const { return ExpandedToEmptyPack; } + /// Determine the location of the 'sizeof' keyword. SourceLocation getEllipsisLoc() const { return EllipsisLoc; } @@ -4445,6 +4455,7 @@ public: return getTrailingObjects()[*Index]; } + /// Return the trailing expressions, regardless of the expansion. ArrayRef getExpressions() const { return {getTrailingObjects(), TransformedExpressions}; } diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 7e9343271ac3..2abc0acbfde3 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -1665,12 +1665,10 @@ NonTypeTemplateParmDecl *SubstNonTypeTemplateParmExpr::getParameter() const { getReplacedTemplateParameterList(getAssociatedDecl())->asArray()[Index]); } -PackIndexingExpr *PackIndexingExpr::Create(ASTContext &Context, - SourceLocation EllipsisLoc, - SourceLocation RSquareLoc, - Expr *PackIdExpr, Expr *IndexExpr, - std::optional Index, - ArrayRef SubstitutedExprs) { +PackIndexingExpr *PackIndexingExpr::Create( + ASTContext &Context, SourceLocation EllipsisLoc, SourceLocation RSquareLoc, + Expr *PackIdExpr, Expr *IndexExpr, std::optional Index, + ArrayRef SubstitutedExprs, bool ExpandedToEmptyPack) { QualType Type; if (Index && !SubstitutedExprs.empty()) Type = SubstitutedExprs[*Index]->getType(); @@ -1679,8 +1677,9 @@ PackIndexingExpr *PackIndexingExpr::Create(ASTContext &Context, void *Storage = Context.Allocate(totalSizeToAlloc(SubstitutedExprs.size())); - return new (Storage) PackIndexingExpr( - Type, EllipsisLoc, RSquareLoc, PackIdExpr, IndexExpr, SubstitutedExprs); + return new (Storage) + PackIndexingExpr(Type, EllipsisLoc, RSquareLoc, PackIdExpr, IndexExpr, + SubstitutedExprs, ExpandedToEmptyPack); } NamedDecl *PackIndexingExpr::getPackDecl() const { diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index a4b681ae4f00..0b2060466506 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -1128,7 +1128,7 @@ Sema::BuildPackIndexingExpr(Expr *PackExpression, SourceLocation EllipsisLoc, return PackIndexingExpr::Create(getASTContext(), EllipsisLoc, RSquareLoc, PackExpression, IndexExpr, Index, - ExpandedExprs); + ExpandedExprs, EmptyPack); } TemplateArgumentLoc Sema::getTemplateArgumentPackExpansionPattern( diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index d99bb2032060..06ed0843ef50 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -14967,7 +14967,7 @@ TreeTransform::TransformPackIndexingExpr(PackIndexingExpr *E) { return ExprError(); SmallVector ExpandedExprs; - if (E->getExpressions().empty()) { + if (!E->expandsToEmptyPack() && E->getExpressions().empty()) { Expr *Pattern = E->getPackIdExpression(); SmallVector Unexpanded; getSema().collectUnexpandedParameterPacks(E->getPackIdExpression(), @@ -15021,9 +15021,7 @@ TreeTransform::TransformPackIndexingExpr(PackIndexingExpr *E) { return true; ExpandedExprs.push_back(Out.get()); } - } - - else { + } else if (!E->expandsToEmptyPack()) { if (getDerived().TransformExprs(E->getExpressions().data(), E->getExpressions().size(), false, ExpandedExprs)) diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 7d3930022a69..eac4faff2854 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2177,6 +2177,7 @@ void ASTStmtReader::VisitSizeOfPackExpr(SizeOfPackExpr *E) { void ASTStmtReader::VisitPackIndexingExpr(PackIndexingExpr *E) { VisitExpr(E); E->TransformedExpressions = Record.readInt(); + E->ExpandedToEmptyPack = Record.readInt(); E->EllipsisLoc = readSourceLocation(); E->RSquareLoc = readSourceLocation(); E->SubExprs[0] = Record.readStmt(); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 6f7c368ce9ca..a44852af97be 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2157,11 +2157,11 @@ void ASTStmtWriter::VisitSizeOfPackExpr(SizeOfPackExpr *E) { void ASTStmtWriter::VisitPackIndexingExpr(PackIndexingExpr *E) { VisitExpr(E); Record.push_back(E->TransformedExpressions); + Record.push_back(E->ExpandedToEmptyPack); Record.AddSourceLocation(E->getEllipsisLoc()); Record.AddSourceLocation(E->getRSquareLoc()); Record.AddStmt(E->getPackIdExpression()); Record.AddStmt(E->getIndexExpr()); - Record.push_back(E->TransformedExpressions); for (Expr *Sub : E->getExpressions()) Record.AddStmt(Sub); Code = serialization::EXPR_PACK_INDEXING; diff --git a/clang/test/PCH/pack_indexing.cpp b/clang/test/PCH/pack_indexing.cpp index cf8124617b3c..1c4dac0fd9a3 100644 --- a/clang/test/PCH/pack_indexing.cpp +++ b/clang/test/PCH/pack_indexing.cpp @@ -10,7 +10,11 @@ using Type = U...[I]; template constexpr auto Var = V...[I]; +template +decltype(V...[I]) foo() { return V...[I]; } + void fn1() { using A = Type<1, int, long, double>; constexpr auto V = Var<2, 0, 1, 42>; + foo<2, 0, 1, 42>(); } diff --git a/clang/test/SemaCXX/cxx2c-pack-indexing.cpp b/clang/test/SemaCXX/cxx2c-pack-indexing.cpp index 0ac85b5bcc14..28b9765127f4 100644 --- a/clang/test/SemaCXX/cxx2c-pack-indexing.cpp +++ b/clang/test/SemaCXX/cxx2c-pack-indexing.cpp @@ -206,13 +206,17 @@ void test(auto...args){ template void test2(){ [&](){ - using R = decltype( args...[idx] ) ; - }.template operator()<0>(); + using R = decltype( args...[idx] ) ; // #test2-R + }.template operator()<0>(); // #test2-call } void f( ) { test(1); test2<1>(); + test2(); + // expected-error@#test2-R {{invalid index 0 for pack args of size 0}} + // expected-note@#test2-call {{requested here}} + // expected-note@-3 {{requested here}} } -- GitLab From 4cebe5a43ba83eab477358ef4da665b43463bb68 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Sun, 19 May 2024 22:06:29 -0300 Subject: [PATCH 150/793] [clang] NFC: add test for cwg2398 ambiguity issue --- clang/test/SemaTemplate/cwg2398.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/clang/test/SemaTemplate/cwg2398.cpp b/clang/test/SemaTemplate/cwg2398.cpp index 31686c4bc980..e3b5e575374d 100644 --- a/clang/test/SemaTemplate/cwg2398.cpp +++ b/clang/test/SemaTemplate/cwg2398.cpp @@ -59,6 +59,21 @@ namespace templ { template struct C>; } // namespace templ +namespace class_template { + template struct A; + + template struct B; + + template