2 changes: 2 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -802,9 +802,11 @@ def B : JoinedOrSeparate<["-"], "B">, MetaVarName<"<prefix>">,
HelpText<"Search $prefix$file for executables, libraries, and data files. "
"If $prefix is a directory, search $prefix/$file">;
def gcc_install_dir_EQ : Joined<["--"], "gcc-install-dir=">,
Visibility<[ClangOption, FlangOption]>,
HelpText<"Use GCC installation in the specified directory. The directory ends with path components like 'lib{,32,64}/gcc{,-cross}/$triple/$version'. "
"Note: executables (e.g. ld) used by the compiler are not overridden by the selected GCC installation">;
def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[NoXarchOption]>,
Visibility<[ClangOption, FlangOption]>,
HelpText<"Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. "
"Clang will use the GCC installation with the largest version">;
def gcc_triple_EQ : Joined<["--"], "gcc-triple=">,
Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,9 @@ class FrontendOptions {
BuildingImplicitModuleUsesLock(true), ModulesEmbedAllFiles(false),
IncludeTimestamps(true), UseTemporary(true),
AllowPCMWithCompilerErrors(false), ModulesShareFileManager(true),
TimeTraceGranularity(500) {}
EmitSymbolGraph(false), EmitExtensionSymbolGraphs(false),
EmitSymbolGraphSymbolLabelsForTesting(false),
EmitPrettySymbolGraphs(false), TimeTraceGranularity(500) {}

/// getInputKindForExtension - Return the appropriate input kind for a file
/// extension. For example, "c" would return Language::C.
Expand Down
13 changes: 7 additions & 6 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1746,14 +1746,15 @@ void TypePrinter::printPackExpansionAfter(const PackExpansionType *T,
static void printCountAttributedImpl(const CountAttributedType *T,
raw_ostream &OS,
const PrintingPolicy &Policy) {
OS << ' ';
if (T->isCountInBytes() && T->isOrNull())
OS << " __sized_by_or_null(";
OS << "__sized_by_or_null(";
else if (T->isCountInBytes())
OS << " __sized_by(";
OS << "__sized_by(";
else if (T->isOrNull())
OS << " __counted_by_or_null(";
OS << "__counted_by_or_null(";
else
OS << " __counted_by(";
OS << "__counted_by(";
if (T->getCountExpr())
T->getCountExpr()->printPretty(OS, nullptr, Policy);
OS << ')';
Expand All @@ -1762,14 +1763,14 @@ static void printCountAttributedImpl(const CountAttributedType *T,
void TypePrinter::printCountAttributedBefore(const CountAttributedType *T,
raw_ostream &OS) {
printBefore(T->desugar(), OS);
if (!T->desugar()->isArrayType())
if (!T->isArrayType())
printCountAttributedImpl(T, OS, Policy);
}

void TypePrinter::printCountAttributedAfter(const CountAttributedType *T,
raw_ostream &OS) {
printAfter(T->desugar(), OS);
if (T->desugar()->isArrayType())
if (T->isArrayType())
printCountAttributedImpl(T, OS, Policy);
}

Expand Down
49 changes: 25 additions & 24 deletions clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,17 +166,16 @@ static Value *joinDistinctValues(QualType Type, Value &Val1,
return JoinedVal;
}

// When widening does not change `Current`, return value will equal `&Prev`.
static Value &widenDistinctValues(QualType Type, Value &Prev,
const Environment &PrevEnv, Value &Current,
Environment &CurrentEnv,
Environment::ValueModel &Model) {
static WidenResult widenDistinctValues(QualType Type, Value &Prev,
const Environment &PrevEnv,
Value &Current, Environment &CurrentEnv,
Environment::ValueModel &Model) {
// Boolean-model widening.
if (auto *PrevBool = dyn_cast<BoolValue>(&Prev)) {
// If previous value was already Top, re-use that to (implicitly) indicate
// that no change occurred.
if (isa<TopBoolValue>(Prev))
return Prev;
// Safe to return `Prev` here, because Top is never dependent on the
// environment.
return {&Prev, LatticeEffect::Unchanged};

// We may need to widen to Top, but before we do so, check whether both
// values are implied to be either true or false in the current environment.
Expand All @@ -185,22 +184,24 @@ static Value &widenDistinctValues(QualType Type, Value &Prev,
bool TruePrev = PrevEnv.proves(PrevBool->formula());
bool TrueCur = CurrentEnv.proves(CurBool.formula());
if (TruePrev && TrueCur)
return CurrentEnv.getBoolLiteralValue(true);
return {&CurrentEnv.getBoolLiteralValue(true), LatticeEffect::Unchanged};
if (!TruePrev && !TrueCur &&
PrevEnv.proves(PrevEnv.arena().makeNot(PrevBool->formula())) &&
CurrentEnv.proves(CurrentEnv.arena().makeNot(CurBool.formula())))
return CurrentEnv.getBoolLiteralValue(false);
return {&CurrentEnv.getBoolLiteralValue(false), LatticeEffect::Unchanged};

return CurrentEnv.makeTopBoolValue();
return {&CurrentEnv.makeTopBoolValue(), LatticeEffect::Changed};
}

// FIXME: Add other built-in model widening.

// Custom-model widening.
if (auto *W = Model.widen(Type, Prev, PrevEnv, Current, CurrentEnv))
return *W;
if (auto Result = Model.widen(Type, Prev, PrevEnv, Current, CurrentEnv))
return *Result;

return equateUnknownValues(Prev.getKind()) ? Prev : Current;
return {&Current, equateUnknownValues(Prev.getKind())
? LatticeEffect::Unchanged
: LatticeEffect::Changed};
}

// Returns whether the values in `Map1` and `Map2` compare equal for those
Expand Down Expand Up @@ -271,7 +272,7 @@ llvm::MapVector<Key, Value *>
widenKeyToValueMap(const llvm::MapVector<Key, Value *> &CurMap,
const llvm::MapVector<Key, Value *> &PrevMap,
Environment &CurEnv, const Environment &PrevEnv,
Environment::ValueModel &Model, LatticeJoinEffect &Effect) {
Environment::ValueModel &Model, LatticeEffect &Effect) {
llvm::MapVector<Key, Value *> WidenedMap;
for (auto &Entry : CurMap) {
Key K = Entry.first;
Expand All @@ -290,11 +291,11 @@ widenKeyToValueMap(const llvm::MapVector<Key, Value *> &CurMap,
continue;
}

Value &WidenedVal = widenDistinctValues(K->getType(), *PrevIt->second,
PrevEnv, *Val, CurEnv, Model);
WidenedMap.insert({K, &WidenedVal});
if (&WidenedVal != PrevIt->second)
Effect = LatticeJoinEffect::Changed;
auto [WidenedVal, ValEffect] = widenDistinctValues(
K->getType(), *PrevIt->second, PrevEnv, *Val, CurEnv, Model);
WidenedMap.insert({K, WidenedVal});
if (ValEffect == LatticeEffect::Changed)
Effect = LatticeEffect::Changed;
}

return WidenedMap;
Expand Down Expand Up @@ -617,15 +618,15 @@ bool Environment::equivalentTo(const Environment &Other,
return true;
}

LatticeJoinEffect Environment::widen(const Environment &PrevEnv,
Environment::ValueModel &Model) {
LatticeEffect Environment::widen(const Environment &PrevEnv,
Environment::ValueModel &Model) {
assert(DACtx == PrevEnv.DACtx);
assert(ReturnVal == PrevEnv.ReturnVal);
assert(ReturnLoc == PrevEnv.ReturnLoc);
assert(ThisPointeeLoc == PrevEnv.ThisPointeeLoc);
assert(CallStack == PrevEnv.CallStack);

auto Effect = LatticeJoinEffect::Unchanged;
auto Effect = LatticeEffect::Unchanged;

// By the API, `PrevEnv` is a previous version of the environment for the same
// block, so we have some guarantees about its shape. In particular, it will
Expand All @@ -646,7 +647,7 @@ LatticeJoinEffect Environment::widen(const Environment &PrevEnv,
ExprToLoc.size() != PrevEnv.ExprToLoc.size() ||
ExprToVal.size() != PrevEnv.ExprToVal.size() ||
LocToVal.size() != PrevEnv.LocToVal.size())
Effect = LatticeJoinEffect::Changed;
Effect = LatticeEffect::Changed;

return Effect;
}
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/Basic/Targets/Mips.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
FPMode = isFP64Default() ? FP64 : FPXX;
NoOddSpreg = false;
bool OddSpregGiven = false;
bool StrictAlign = false;

for (const auto &Feature : Features) {
if (Feature == "+single-float")
Expand All @@ -330,6 +331,10 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
IsMicromips = true;
else if (Feature == "+mips32r6" || Feature == "+mips64r6")
HasUnalignedAccess = true;
// We cannot be sure that the order of strict-align vs mips32r6.
// Thus we need an extra variable here.
else if (Feature == "+strict-align")
StrictAlign = true;
else if (Feature == "+dsp")
DspRev = std::max(DspRev, DSP1);
else if (Feature == "+dspr2")
Expand Down Expand Up @@ -368,6 +373,9 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
if (FPMode == FPXX && !OddSpregGiven)
NoOddSpreg = true;

if (StrictAlign)
HasUnalignedAccess = false;

setDataLayout();

return true;
Expand Down
5 changes: 1 addition & 4 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,6 @@ using namespace llvm;
namespace llvm {
extern cl::opt<bool> PrintPipelinePasses;

static cl::opt<bool> ClRemoveTraps("clang-remove-traps", cl::Optional,
cl::desc("Insert remove-traps pass."));

// Experiment to move sanitizers earlier.
static cl::opt<bool> ClSanitizeOnOptimizerEarlyEP(
"sanitizer-early-opt-ep", cl::Optional,
Expand Down Expand Up @@ -750,7 +747,7 @@ static void addSanitizers(const Triple &TargetTriple,
PB.registerOptimizerLastEPCallback(SanitizersCallback);
}

if (ClRemoveTraps) {
if (RemoveTrapsPass::IsRequested()) {
// We can optimize after inliner, and PGO profile matching. The hook below
// is called at the end `buildFunctionSimplificationPipeline`, which called
// from `buildInlinerPipeline`, which called after profile matching.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGBlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -962,7 +962,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
}

// If it's a reference variable, copy the reference into the block field.
} else if (auto refType = type->getAs<ReferenceType>()) {
} else if (type->getAs<ReferenceType>()) {
Builder.CreateStore(src.emitRawPointer(*this), blockField);

// If type is const-qualified, copy the value into the block field.
Expand Down
10 changes: 0 additions & 10 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7281,8 +7281,6 @@ static const std::pair<unsigned, unsigned> NEONEquivalentIntrinsicMap[] = {
{ NEON::BI__builtin_neon_vabdq_f16, NEON::BI__builtin_neon_vabdq_v, },
{ NEON::BI__builtin_neon_vabs_f16, NEON::BI__builtin_neon_vabs_v, },
{ NEON::BI__builtin_neon_vabsq_f16, NEON::BI__builtin_neon_vabsq_v, },
{ NEON::BI__builtin_neon_vbsl_f16, NEON::BI__builtin_neon_vbsl_v, },
{ NEON::BI__builtin_neon_vbslq_f16, NEON::BI__builtin_neon_vbslq_v, },
{ NEON::BI__builtin_neon_vcage_f16, NEON::BI__builtin_neon_vcage_v, },
{ NEON::BI__builtin_neon_vcageq_f16, NEON::BI__builtin_neon_vcageq_v, },
{ NEON::BI__builtin_neon_vcagt_f16, NEON::BI__builtin_neon_vcagt_v, },
Expand All @@ -7301,8 +7299,6 @@ static const std::pair<unsigned, unsigned> NEONEquivalentIntrinsicMap[] = {
{ NEON::BI__builtin_neon_vclezq_f16, NEON::BI__builtin_neon_vclezq_v, },
{ NEON::BI__builtin_neon_vcltz_f16, NEON::BI__builtin_neon_vcltz_v, },
{ NEON::BI__builtin_neon_vcltzq_f16, NEON::BI__builtin_neon_vcltzq_v, },
{ NEON::BI__builtin_neon_vext_f16, NEON::BI__builtin_neon_vext_v, },
{ NEON::BI__builtin_neon_vextq_f16, NEON::BI__builtin_neon_vextq_v, },
{ NEON::BI__builtin_neon_vfma_f16, NEON::BI__builtin_neon_vfma_v, },
{ NEON::BI__builtin_neon_vfma_lane_f16, NEON::BI__builtin_neon_vfma_lane_v, },
{ NEON::BI__builtin_neon_vfma_laneq_f16, NEON::BI__builtin_neon_vfma_laneq_v, },
Expand Down Expand Up @@ -7405,12 +7401,6 @@ static const std::pair<unsigned, unsigned> NEONEquivalentIntrinsicMap[] = {
{ NEON::BI__builtin_neon_vst4_lane_bf16, NEON::BI__builtin_neon_vst4_lane_v },
{ NEON::BI__builtin_neon_vst4q_bf16, NEON::BI__builtin_neon_vst4q_v },
{ NEON::BI__builtin_neon_vst4q_lane_bf16, NEON::BI__builtin_neon_vst4q_lane_v },
{ NEON::BI__builtin_neon_vtrn_f16, NEON::BI__builtin_neon_vtrn_v, },
{ NEON::BI__builtin_neon_vtrnq_f16, NEON::BI__builtin_neon_vtrnq_v, },
{ NEON::BI__builtin_neon_vuzp_f16, NEON::BI__builtin_neon_vuzp_v, },
{ NEON::BI__builtin_neon_vuzpq_f16, NEON::BI__builtin_neon_vuzpq_v, },
{ NEON::BI__builtin_neon_vzip_f16, NEON::BI__builtin_neon_vzip_v, },
{ NEON::BI__builtin_neon_vzipq_f16, NEON::BI__builtin_neon_vzipq_v, },
// The mangling rules cause us to have one ID for each type for vldap1(q)_lane
// and vstl1(q)_lane, but codegen is equivalent for all of them. Choose an
// arbitrary one to be handled as tha canonical variation.
Expand Down
37 changes: 2 additions & 35 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5580,44 +5580,11 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
break;
}

// TODO: Can we de-duplicate this code with the corresponding code in
// CGExprScalar, similar to the way EmitCompoundAssignmentLValue works?
RValue RV;
llvm::Value *Previous = nullptr;
QualType SrcType = E->getRHS()->getType();
// Check if LHS is a bitfield, if RHS contains an implicit cast expression
// we want to extract that value and potentially (if the bitfield sanitizer
// is enabled) use it to check for an implicit conversion.
if (E->getLHS()->refersToBitField()) {
llvm::Value *RHS =
EmitWithOriginalRHSBitfieldAssignment(E, Previous, &SrcType);
RV = RValue::get(RHS);
} else
RV = EmitAnyExpr(E->getRHS());

RValue RV = EmitAnyExpr(E->getRHS());
LValue LV = EmitCheckedLValue(E->getLHS(), TCK_Store);

if (RV.isScalar())
EmitNullabilityCheck(LV, RV.getScalarVal(), E->getExprLoc());

if (LV.isBitField()) {
llvm::Value *Result;
// If bitfield sanitizers are enabled we want to use the result
// to check whether a truncation or sign change has occurred.
if (SanOpts.has(SanitizerKind::ImplicitBitfieldConversion))
EmitStoreThroughBitfieldLValue(RV, LV, &Result);
else
EmitStoreThroughBitfieldLValue(RV, LV);

// If the expression contained an implicit conversion, make sure
// to use the value before the scalar conversion.
llvm::Value *Src = Previous ? Previous : RV.getScalarVal();
QualType DstType = E->getLHS()->getType();
EmitBitfieldConversionCheck(Src, SrcType, Result, DstType,
LV.getBitFieldInfo(), E->getExprLoc());
} else
EmitStoreThroughLValue(RV, LV);

EmitStoreThroughLValue(RV, LV);
if (getLangOpts().OpenMP)
CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(*this,
E->getLHS());
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/CGExprComplex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,12 +319,12 @@ class ComplexExprEmitter
// doubles the exponent of SmallerType.LargestFiniteVal)
if (llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 <=
llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) {
FPHasBeenPromoted = true;
return CGF.getContext().getComplexType(HigherElementType);
} else {
FPHasBeenPromoted = true;
DiagnosticsEngine &Diags = CGF.CGM.getDiags();
Diags.Report(diag::warn_next_larger_fp_type_same_size_than_fp);
return CGF.getContext().getComplexType(ElementType);
return QualType();
}
}

Expand Down Expand Up @@ -1037,7 +1037,7 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
LHSi = llvm::Constant::getNullValue(RHSi->getType());
if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Improved ||
(Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted &&
FPHasBeenPromoted))
!FPHasBeenPromoted))
return EmitRangeReductionDiv(LHSr, LHSi, RHSr, RHSi);
else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Basic ||
Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted)
Expand Down
257 changes: 32 additions & 225 deletions clang/lib/CodeGen/CGExprScalar.cpp

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions clang/lib/CodeGen/CGOpenMPRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2648,9 +2648,9 @@ void CGOpenMPRuntime::emitDistributeStaticInit(
void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
SourceLocation Loc,
OpenMPDirectiveKind DKind) {
assert(DKind == OMPD_distribute || DKind == OMPD_for ||
DKind == OMPD_sections &&
"Expected distribute, for, or sections directive kind");
assert((DKind == OMPD_distribute || DKind == OMPD_for ||
DKind == OMPD_sections) &&
"Expected distribute, for, or sections directive kind");
if (!CGF.HaveInsertPoint())
return;
// Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Expand Down
15 changes: 0 additions & 15 deletions clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -2786,21 +2786,6 @@ class CodeGenFunction : public CodeGenTypeCache {
/// expression and compare the result against zero, returning an Int1Ty value.
llvm::Value *EvaluateExprAsBool(const Expr *E);

/// Retrieve the implicit cast expression of the rhs in a binary operator
/// expression by passing pointers to Value and QualType
/// This is used for implicit bitfield conversion checks, which
/// must compare with the value before potential truncation.
llvm::Value *EmitWithOriginalRHSBitfieldAssignment(const BinaryOperator *E,
llvm::Value *Previous,
QualType *SrcType);

/// Emit a check that an [implicit] conversion of a bitfield. It is not UB,
/// so we use the value after conversion.
void EmitBitfieldConversionCheck(llvm::Value *Src, QualType SrcType,
llvm::Value *Dst, QualType DstType,
const CGBitFieldInfo &Info,
SourceLocation Loc);

/// EmitIgnoredExpr - Emit an expression in a context which ignores the result.
void EmitIgnoredExpr(const Expr *E);

Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5882,7 +5882,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CM = "large";
if (Triple.isAArch64(64)) {
Ok = CM == "tiny" || CM == "small" || CM == "large";
if (CM == "large" && RelocationModel != llvm::Reloc::Static)
if (CM == "large" && !Triple.isOSBinFormatMachO() &&
RelocationModel != llvm::Reloc::Static)
D.Diag(diag::err_drv_argument_only_allowed_with)
<< A->getAsString(Args) << "-fno-pic";
} else if (Triple.isLoongArch()) {
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Headers/__stddef_unreachable.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
*===-----------------------------------------------------------------------===
*/

#ifndef __cplusplus

/*
* When -fbuiltin-headers-in-system-modules is set this is a non-modular header
* and needs to behave as if it was textual.
Expand All @@ -15,3 +17,5 @@
(__has_feature(modules) && !__building_module(_Builtin_stddef))
#define unreachable() __builtin_unreachable()
#endif

#endif
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2751,7 +2751,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
QualType type = VD->getType().getNonReferenceType();
// This will eventually be translated into MemberExpr upon
// the use of instantiated struct fields.
return BuildDeclRefExpr(VD, type, VK_PRValue, NameLoc);
return BuildDeclRefExpr(VD, type, VK_LValue, NameLoc);
}
}
}
Expand Down
1 change: 0 additions & 1 deletion clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2711,7 +2711,6 @@ SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList(
: TemplateParams(TemplateParams.begin(), TemplateParams.end()) {}

bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
TTP->getIndex();
MarkAppeared(TTP->getDecl());
return true;
}
Expand Down
485 changes: 485 additions & 0 deletions clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics-generic.c

Large diffs are not rendered by default.

472 changes: 0 additions & 472 deletions clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c

Large diffs are not rendered by default.

207 changes: 207 additions & 0 deletions clang/test/CodeGen/allow-ubsan-check.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,null | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,null -fsanitize-trap=signed-integer-overflow,integer-divide-by-zero,null | FileCheck %s --check-prefixes=TRAP
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -o - %s -fsanitize=signed-integer-overflow,integer-divide-by-zero,null -fsanitize-recover=signed-integer-overflow,integer-divide-by-zero,null | FileCheck %s --check-prefixes=RECOVER


// CHECK-LABEL: define dso_local i32 @div(
// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[Y_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
// CHECK-NEXT: store i32 [[Y]], ptr [[Y_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
// CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0, !nosanitize [[META2:![0-9]+]]
// CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP0]], -2147483648, !nosanitize [[META2]]
// CHECK-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP1]], -1, !nosanitize [[META2]]
// CHECK-NEXT: [[OR:%.*]] = or i1 [[TMP3]], [[TMP4]], !nosanitize [[META2]]
// CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP2]], [[OR]], !nosanitize [[META2]]
// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[HANDLER_DIVREM_OVERFLOW:%.*]], !prof [[PROF3:![0-9]+]], !nosanitize [[META2]]
// CHECK: handler.divrem_overflow:
// CHECK-NEXT: [[TMP6:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META2]]
// CHECK-NEXT: [[TMP7:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META2]]
// CHECK-NEXT: call void @__ubsan_handle_divrem_overflow_abort(ptr @[[GLOB1:[0-9]+]], i64 [[TMP6]], i64 [[TMP7]]) #[[ATTR3:[0-9]+]], !nosanitize [[META2]]
// CHECK-NEXT: unreachable, !nosanitize [[META2]]
// CHECK: cont:
// CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP0]], [[TMP1]]
// CHECK-NEXT: ret i32 [[DIV]]
//
// TRAP-LABEL: define dso_local i32 @div(
// TRAP-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0:[0-9]+]] {
// TRAP-NEXT: entry:
// TRAP-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
// TRAP-NEXT: [[Y_ADDR:%.*]] = alloca i32, align 4
// TRAP-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
// TRAP-NEXT: store i32 [[Y]], ptr [[Y_ADDR]], align 4
// TRAP-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
// TRAP-NEXT: [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
// TRAP-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0, !nosanitize [[META2:![0-9]+]]
// TRAP-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP0]], -2147483648, !nosanitize [[META2]]
// TRAP-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP1]], -1, !nosanitize [[META2]]
// TRAP-NEXT: [[OR:%.*]] = or i1 [[TMP3]], [[TMP4]], !nosanitize [[META2]]
// TRAP-NEXT: [[TMP5:%.*]] = and i1 [[TMP2]], [[OR]], !nosanitize [[META2]]
// TRAP-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], !nosanitize [[META2]]
// TRAP: trap:
// TRAP-NEXT: call void @llvm.ubsantrap(i8 3) #[[ATTR3:[0-9]+]], !nosanitize [[META2]]
// TRAP-NEXT: unreachable, !nosanitize [[META2]]
// TRAP: cont:
// TRAP-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP0]], [[TMP1]]
// TRAP-NEXT: ret i32 [[DIV]]
//
// RECOVER-LABEL: define dso_local i32 @div(
// RECOVER-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0:[0-9]+]] {
// RECOVER-NEXT: entry:
// RECOVER-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
// RECOVER-NEXT: [[Y_ADDR:%.*]] = alloca i32, align 4
// RECOVER-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
// RECOVER-NEXT: store i32 [[Y]], ptr [[Y_ADDR]], align 4
// RECOVER-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
// RECOVER-NEXT: [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
// RECOVER-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0, !nosanitize [[META2:![0-9]+]]
// RECOVER-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP0]], -2147483648, !nosanitize [[META2]]
// RECOVER-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP1]], -1, !nosanitize [[META2]]
// RECOVER-NEXT: [[OR:%.*]] = or i1 [[TMP3]], [[TMP4]], !nosanitize [[META2]]
// RECOVER-NEXT: [[TMP5:%.*]] = and i1 [[TMP2]], [[OR]], !nosanitize [[META2]]
// RECOVER-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[HANDLER_DIVREM_OVERFLOW:%.*]], !prof [[PROF3:![0-9]+]], !nosanitize [[META2]]
// RECOVER: handler.divrem_overflow:
// RECOVER-NEXT: [[TMP6:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META2]]
// RECOVER-NEXT: [[TMP7:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META2]]
// RECOVER-NEXT: call void @__ubsan_handle_divrem_overflow(ptr @[[GLOB1:[0-9]+]], i64 [[TMP6]], i64 [[TMP7]]) #[[ATTR3:[0-9]+]], !nosanitize [[META2]]
// RECOVER-NEXT: br label [[CONT]], !nosanitize [[META2]]
// RECOVER: cont:
// RECOVER-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP0]], [[TMP1]]
// RECOVER-NEXT: ret i32 [[DIV]]
//
int div(int x, int y) {
return x / y;
}

// CHECK-LABEL: define dso_local i32 @null(
// CHECK-SAME: ptr noundef [[X:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[X_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NEXT: store ptr [[X]], ptr [[X_ADDR]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X_ADDR]], align 8
// CHECK-NEXT: [[TMP1:%.*]] = icmp ne ptr [[TMP0]], null, !nosanitize [[META2]]
// CHECK-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[HANDLER_TYPE_MISMATCH:%.*]], !prof [[PROF3]], !nosanitize [[META2]]
// CHECK: handler.type_mismatch:
// CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP0]] to i64, !nosanitize [[META2]]
// CHECK-NEXT: call void @__ubsan_handle_type_mismatch_v1_abort(ptr @[[GLOB2:[0-9]+]], i64 [[TMP2]]) #[[ATTR3]], !nosanitize [[META2]]
// CHECK-NEXT: unreachable, !nosanitize [[META2]]
// CHECK: cont:
// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP0]], align 4
// CHECK-NEXT: ret i32 [[TMP3]]
//
// TRAP-LABEL: define dso_local i32 @null(
// TRAP-SAME: ptr noundef [[X:%.*]]) #[[ATTR0]] {
// TRAP-NEXT: entry:
// TRAP-NEXT: [[X_ADDR:%.*]] = alloca ptr, align 8
// TRAP-NEXT: store ptr [[X]], ptr [[X_ADDR]], align 8
// TRAP-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X_ADDR]], align 8
// TRAP-NEXT: [[TMP1:%.*]] = icmp ne ptr [[TMP0]], null, !nosanitize [[META2]]
// TRAP-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[TRAP:%.*]], !nosanitize [[META2]]
// TRAP: trap:
// TRAP-NEXT: call void @llvm.ubsantrap(i8 22) #[[ATTR3]], !nosanitize [[META2]]
// TRAP-NEXT: unreachable, !nosanitize [[META2]]
// TRAP: cont:
// TRAP-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP0]], align 4
// TRAP-NEXT: ret i32 [[TMP2]]
//
// RECOVER-LABEL: define dso_local i32 @null(
// RECOVER-SAME: ptr noundef [[X:%.*]]) #[[ATTR0]] {
// RECOVER-NEXT: entry:
// RECOVER-NEXT: [[X_ADDR:%.*]] = alloca ptr, align 8
// RECOVER-NEXT: store ptr [[X]], ptr [[X_ADDR]], align 8
// RECOVER-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X_ADDR]], align 8
// RECOVER-NEXT: [[TMP1:%.*]] = icmp ne ptr [[TMP0]], null, !nosanitize [[META2]]
// RECOVER-NEXT: br i1 [[TMP1]], label [[CONT:%.*]], label [[HANDLER_TYPE_MISMATCH:%.*]], !prof [[PROF3]], !nosanitize [[META2]]
// RECOVER: handler.type_mismatch:
// RECOVER-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP0]] to i64, !nosanitize [[META2]]
// RECOVER-NEXT: call void @__ubsan_handle_type_mismatch_v1(ptr @[[GLOB2:[0-9]+]], i64 [[TMP2]]) #[[ATTR3]], !nosanitize [[META2]]
// RECOVER-NEXT: br label [[CONT]], !nosanitize [[META2]]
// RECOVER: cont:
// RECOVER-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP0]], align 4
// RECOVER-NEXT: ret i32 [[TMP3]]
//
int null(int* x) {
return *x;
}

// CHECK-LABEL: define dso_local i32 @overflow(
// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[Y_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
// CHECK-NEXT: store i32 [[Y]], ptr [[Y_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
// CHECK-NEXT: [[TMP2:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[TMP0]], i32 [[TMP1]]), !nosanitize [[META2]]
// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP2]], 0, !nosanitize [[META2]]
// CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP2]], 1, !nosanitize [[META2]]
// CHECK-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true, !nosanitize [[META2]]
// CHECK-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[HANDLER_ADD_OVERFLOW:%.*]], !prof [[PROF3]], !nosanitize [[META2]]
// CHECK: handler.add_overflow:
// CHECK-NEXT: [[TMP6:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META2]]
// CHECK-NEXT: [[TMP7:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META2]]
// CHECK-NEXT: call void @__ubsan_handle_add_overflow_abort(ptr @[[GLOB3:[0-9]+]], i64 [[TMP6]], i64 [[TMP7]]) #[[ATTR3]], !nosanitize [[META2]]
// CHECK-NEXT: unreachable, !nosanitize [[META2]]
// CHECK: cont:
// CHECK-NEXT: ret i32 [[TMP3]]
//
// TRAP-LABEL: define dso_local i32 @overflow(
// TRAP-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
// TRAP-NEXT: entry:
// TRAP-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
// TRAP-NEXT: [[Y_ADDR:%.*]] = alloca i32, align 4
// TRAP-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
// TRAP-NEXT: store i32 [[Y]], ptr [[Y_ADDR]], align 4
// TRAP-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
// TRAP-NEXT: [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
// TRAP-NEXT: [[TMP2:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[TMP0]], i32 [[TMP1]]), !nosanitize [[META2]]
// TRAP-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP2]], 0, !nosanitize [[META2]]
// TRAP-NEXT: [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP2]], 1, !nosanitize [[META2]]
// TRAP-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true, !nosanitize [[META2]]
// TRAP-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[TRAP:%.*]], !nosanitize [[META2]]
// TRAP: trap:
// TRAP-NEXT: call void @llvm.ubsantrap(i8 0) #[[ATTR3]], !nosanitize [[META2]]
// TRAP-NEXT: unreachable, !nosanitize [[META2]]
// TRAP: cont:
// TRAP-NEXT: ret i32 [[TMP3]]
//
// RECOVER-LABEL: define dso_local i32 @overflow(
// RECOVER-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
// RECOVER-NEXT: entry:
// RECOVER-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
// RECOVER-NEXT: [[Y_ADDR:%.*]] = alloca i32, align 4
// RECOVER-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
// RECOVER-NEXT: store i32 [[Y]], ptr [[Y_ADDR]], align 4
// RECOVER-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
// RECOVER-NEXT: [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
// RECOVER-NEXT: [[TMP2:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[TMP0]], i32 [[TMP1]]), !nosanitize [[META2]]
// RECOVER-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP2]], 0, !nosanitize [[META2]]
// RECOVER-NEXT: [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP2]], 1, !nosanitize [[META2]]
// RECOVER-NEXT: [[TMP5:%.*]] = xor i1 [[TMP4]], true, !nosanitize [[META2]]
// RECOVER-NEXT: br i1 [[TMP5]], label [[CONT:%.*]], label [[HANDLER_ADD_OVERFLOW:%.*]], !prof [[PROF3]], !nosanitize [[META2]]
// RECOVER: handler.add_overflow:
// RECOVER-NEXT: [[TMP6:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META2]]
// RECOVER-NEXT: [[TMP7:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META2]]
// RECOVER-NEXT: call void @__ubsan_handle_add_overflow(ptr @[[GLOB3:[0-9]+]], i64 [[TMP6]], i64 [[TMP7]]) #[[ATTR3]], !nosanitize [[META2]]
// RECOVER-NEXT: br label [[CONT]], !nosanitize [[META2]]
// RECOVER: cont:
// RECOVER-NEXT: ret i32 [[TMP3]]
//
int overflow(int x, int y) {
return x + y;
}
//.
// CHECK: [[META2]] = !{}
// CHECK: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1}
//.
// TRAP: [[META2]] = !{}
//.
// RECOVER: [[META2]] = !{}
// RECOVER: [[PROF3]] = !{!"branch_weights", i32 1048575, i32 1}
//.
600 changes: 600 additions & 0 deletions clang/test/CodeGen/arm-v8.2a-neon-intrinsics-generic.c

Large diffs are not rendered by default.

178 changes: 0 additions & 178 deletions clang/test/CodeGen/arm-v8.2a-neon-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -817,181 +817,3 @@ float16x4_t test_vmul_n_f16(float16x4_t a, float16_t b) {
float16x8_t test_vmulq_n_f16(float16x8_t a, float16_t b) {
return vmulq_n_f16(a, b);
}

// CHECK-LABEL: test_vbsl_f16
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x half> %c to <8 x i8>
// CHECK: [[VBSL:%.*]] = call <8 x i8> @llvm.arm.neon.vbsl.v8i8(<8 x i8> [[TMP0]], <8 x i8> [[TMP1]], <8 x i8> [[TMP2]])
// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[VBSL]] to <4 x half>
// CHECK: ret <4 x half> [[TMP3]]
float16x4_t test_vbsl_f16(uint16x4_t a, float16x4_t b, float16x4_t c) {
return vbsl_f16(a, b, c);
}

// CHECK-LABEL: test_vbslq_f16
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x half> %c to <16 x i8>
// CHECK: [[VBSL:%.*]] = call <16 x i8> @llvm.arm.neon.vbsl.v16i8(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]], <16 x i8> [[TMP2]])
// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[VBSL]] to <8 x half>
// CHECK: ret <8 x half> [[TMP3]]
float16x8_t test_vbslq_f16(uint16x8_t a, float16x8_t b, float16x8_t c) {
return vbslq_f16(a, b, c);
}

// CHECK-LABEL: test_vzip_f16
// CHECK: [[VZIP0:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
// CHECK: store <4 x half> [[VZIP0]], ptr [[addr1:%.*]]
// CHECK: [[VZIP1:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: store <4 x half> [[VZIP1]], ptr [[addr2:%.*]]
float16x4x2_t test_vzip_f16(float16x4_t a, float16x4_t b) {
return vzip_f16(a, b);
}

// CHECK-LABEL: test_vzipq_f16
// CHECK: [[VZIP0:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
// CHECK: store <8 x half> [[VZIP0]], ptr [[addr1:%.*]]
// CHECK: [[VZIP1:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
// CHECK: store <8 x half> [[VZIP1]], ptr [[addr2:%.*]]
float16x8x2_t test_vzipq_f16(float16x8_t a, float16x8_t b) {
return vzipq_f16(a, b);
}

// CHECK-LABEL: test_vuzp_f16
// CHECK: [[VUZP0:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
// CHECK: store <4 x half> [[VUZP0]], ptr [[addr1:%.*]]
// CHECK: [[VUZP1:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: store <4 x half> [[VUZP1]], ptr [[addr1:%.*]]
float16x4x2_t test_vuzp_f16(float16x4_t a, float16x4_t b) {
return vuzp_f16(a, b);
}

// CHECK-LABEL: test_vuzpq_f16
// CHECK: [[VUZP0:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
// CHECK: store <8 x half> [[VUZP0]], ptr [[addr1:%.*]]
// CHECK: [[VUZP1:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
// CHECK: store <8 x half> [[VUZP1]], ptr [[addr2:%.*]]
float16x8x2_t test_vuzpq_f16(float16x8_t a, float16x8_t b) {
return vuzpq_f16(a, b);
}

// CHECK-LABEL: test_vtrn_f16
// CHECK: [[VTRN0:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
// CHECK: store <4 x half> [[VTRN0]], ptr [[addr1:%.*]]
// CHECK: [[VTRN1:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: store <4 x half> [[VTRN1]], ptr [[addr2:%.*]]
float16x4x2_t test_vtrn_f16(float16x4_t a, float16x4_t b) {
return vtrn_f16(a, b);
}

// CHECK-LABEL: test_vtrnq_f16
// CHECK: [[VTRN0:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
// CHECK: store <8 x half> [[VTRN0]], ptr [[addr1:%.*]]
// CHECK: [[VTRN1:%.*]] = shufflevector <8 x half> %a, <8 x half> %b, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15>
// CHECK: store <8 x half> [[VTRN1]], ptr [[addr2:%.*]]
float16x8x2_t test_vtrnq_f16(float16x8_t a, float16x8_t b) {
return vtrnq_f16(a, b);
}

// CHECK-LABEL: test_vmov_n_f16
// CHECK: [[TMP0:%.*]] = insertelement <4 x half> poison, half [[ARG:%.*]], i32 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x half> [[TMP0]], half [[ARG]], i32 1
// CHECK: [[TMP2:%.*]] = insertelement <4 x half> [[TMP1]], half [[ARG]], i32 2
// CHECK: [[TMP3:%.*]] = insertelement <4 x half> [[TMP2]], half [[ARG]], i32 3
// CHECK: ret <4 x half> [[TMP3]]
float16x4_t test_vmov_n_f16(float16_t a) {
return vmov_n_f16(a);
}

// CHECK-LABEL: test_vmovq_n_f16
// CHECK: [[TMP0:%.*]] = insertelement <8 x half> poison, half [[ARG:%.*]], i32 0
// CHECK: [[TMP1:%.*]] = insertelement <8 x half> [[TMP0]], half [[ARG]], i32 1
// CHECK: [[TMP2:%.*]] = insertelement <8 x half> [[TMP1]], half [[ARG]], i32 2
// CHECK: [[TMP3:%.*]] = insertelement <8 x half> [[TMP2]], half [[ARG]], i32 3
// CHECK: [[TMP4:%.*]] = insertelement <8 x half> [[TMP3]], half [[ARG]], i32 4
// CHECK: [[TMP5:%.*]] = insertelement <8 x half> [[TMP4]], half [[ARG]], i32 5
// CHECK: [[TMP6:%.*]] = insertelement <8 x half> [[TMP5]], half [[ARG]], i32 6
// CHECK: [[TMP7:%.*]] = insertelement <8 x half> [[TMP6]], half [[ARG]], i32 7
// CHECK: ret <8 x half> [[TMP7]]
float16x8_t test_vmovq_n_f16(float16_t a) {
return vmovq_n_f16(a);
}

// CHECK-LABEL: test_vdup_n_f16
// CHECK: [[TMP0:%.*]] = insertelement <4 x half> poison, half [[ARG:%.*]], i32 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x half> [[TMP0]], half [[ARG]], i32 1
// CHECK: [[TMP2:%.*]] = insertelement <4 x half> [[TMP1]], half [[ARG]], i32 2
// CHECK: [[TMP3:%.*]] = insertelement <4 x half> [[TMP2]], half [[ARG]], i32 3
// CHECK: ret <4 x half> [[TMP3]]
float16x4_t test_vdup_n_f16(float16_t a) {
return vdup_n_f16(a);
}

// CHECK-LABEL: test_vdupq_n_f16
// CHECK: [[TMP0:%.*]] = insertelement <8 x half> poison, half [[ARG:%.*]], i32 0
// CHECK: [[TMP1:%.*]] = insertelement <8 x half> [[TMP0]], half [[ARG]], i32 1
// CHECK: [[TMP2:%.*]] = insertelement <8 x half> [[TMP1]], half [[ARG]], i32 2
// CHECK: [[TMP3:%.*]] = insertelement <8 x half> [[TMP2]], half [[ARG]], i32 3
// CHECK: [[TMP4:%.*]] = insertelement <8 x half> [[TMP3]], half [[ARG]], i32 4
// CHECK: [[TMP5:%.*]] = insertelement <8 x half> [[TMP4]], half [[ARG]], i32 5
// CHECK: [[TMP6:%.*]] = insertelement <8 x half> [[TMP5]], half [[ARG]], i32 6
// CHECK: [[TMP7:%.*]] = insertelement <8 x half> [[TMP6]], half [[ARG]], i32 7
// CHECK: ret <8 x half> [[TMP7]]
float16x8_t test_vdupq_n_f16(float16_t a) {
return vdupq_n_f16(a);
}

// CHECK-LABEL: test_vdup_lane_f16
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> [[A:%.*]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
// CHECK: [[LANE:%.*]] = shufflevector <4 x half> [[TMP1]], <4 x half> [[TMP1]], <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: ret <4 x half> [[LANE]]
float16x4_t test_vdup_lane_f16(float16x4_t a) {
return vdup_lane_f16(a, 3);
}

// CHECK-LABEL: test_vdupq_lane_f16
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> [[A:%.*]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
// CHECK: [[LANE:%.*]] = shufflevector <4 x half> [[TMP1]], <4 x half> [[TMP1]], <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: ret <8 x half> [[LANE]]
float16x8_t test_vdupq_lane_f16(float16x4_t a) {
return vdupq_lane_f16(a, 3);
}

// CHECK-LABEL: @test_vext_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x half>
// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x half>
// CHECK: [[VEXT:%.*]] = shufflevector <4 x half> [[TMP2]], <4 x half> [[TMP3]], <4 x i32> <i32 2, i32 3, i32 4, i32 5>
// CHECK: ret <4 x half> [[VEXT]]
float16x4_t test_vext_f16(float16x4_t a, float16x4_t b) {
return vext_f16(a, b, 2);
}

// CHECK-LABEL: @test_vextq_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x half>
// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x half>
// CHECK: [[VEXT:%.*]] = shufflevector <8 x half> [[TMP2]], <8 x half> [[TMP3]], <8 x i32> <i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12>
// CHECK: ret <8 x half> [[VEXT]]
float16x8_t test_vextq_f16(float16x8_t a, float16x8_t b) {
return vextq_f16(a, b, 5);
}

// CHECK-LABEL: @test_vrev64_f16(
// CHECK: [[SHFL:%.*]] = shufflevector <4 x half> %a, <4 x half> %a, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
// CHECK: ret <4 x half> [[SHFL]]
float16x4_t test_vrev64_f16(float16x4_t a) {
return vrev64_f16(a);
}

// CHECK-LABEL: @test_vrev64q_f16(
// CHECK: [[SHFL:%.*]] = shufflevector <8 x half> %a, <8 x half> %a, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK: ret <8 x half> [[SHFL]]
float16x8_t test_vrev64q_f16(float16x8_t a) {
return vrev64q_f16(a);
}
656 changes: 656 additions & 0 deletions clang/test/CodeGen/cx-complex-range.c

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions clang/test/CodeGen/pseudo-probe-emit.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ void foo(int x) {
// CHECK: call void @llvm.pseudoprobe(i64 [[#GUID:]], i64 1, i32 0, i64 -1)
if (x == 0)
// CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 2, i32 0, i64 -1)
bar();
bar(); // probe id : 3
else
// CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 3, i32 0, i64 -1)
go();
// CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 4, i32 0, i64 -1)
// CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 4, i32 0, i64 -1)
go(); // probe id : 5
// CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 6, i32 0, i64 -1)
}
2 changes: 1 addition & 1 deletion clang/test/CodeGen/remote-traps.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -O1 -emit-llvm -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow %s -o - | FileCheck %s
// RUN: %clang_cc1 -O1 -emit-llvm -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -mllvm -clang-remove-traps -mllvm -remove-traps-random-rate=1 %s -o - | FileCheck %s --implicit-check-not="call void @llvm.ubsantrap" --check-prefixes=REMOVE
// RUN: %clang_cc1 -O1 -emit-llvm -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -mllvm -remove-traps-random-rate=1 %s -o - | FileCheck %s --implicit-check-not="call void @llvm.ubsantrap" --check-prefixes=REMOVE

int test(int x) {
return x + 123;
Expand Down
39 changes: 39 additions & 0 deletions clang/test/CodeGen/tbaa-struct-bitfield-endianness.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// RUN: %clang_cc1 -triple aarch64_be-apple-darwin -emit-llvm -o - -O1 %s | \
// RUN: FileCheck -check-prefixes=CHECK,CHECK-BE %s
// RUN: %clang_cc1 -triple aarch64-apple-darwin -emit-llvm -o - -O1 %s | \
// RUN: FileCheck -check-prefixes=CHECK,CHECK-LE %s
//
// Check that TBAA metadata for structs containing bitfields is
// consistent between big and little endian layouts.
//
// FIXME: The metadata below is invalid for the big endian layout: the
// start offset of 2 is incorrect.

struct NamedBitfields {
int f1 : 8;
int f2 : 8;
unsigned f3 : 1;
unsigned f4 : 15;
int f5;
double f6;
};

// CHECK-LABEL: _Z4copyP14NamedBitfieldsS0_
// CHECK-SAME: ptr nocapture noundef writeonly [[A1:%.*]], ptr nocapture noundef readonly [[A2:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) [[A1]], ptr noundef nonnull align 8 dereferenceable(16) [[A2]], i64 16, i1 false), !tbaa.struct [[TBAA_STRUCT2:![0-9]+]]
// CHECK-NEXT: ret void
//
void copy(NamedBitfields *a1, NamedBitfields *a2) {
*a1 = *a2;
}

// CHECK-BE: [[TBAA_STRUCT2]] = !{i64 2, i64 4, [[META3:![0-9]+]], i64 4, i64 4, [[META6:![0-9]+]], i64 8, i64 8, [[META8:![0-9]+]]}
// CHECK-LE: [[TBAA_STRUCT2]] = !{i64 0, i64 4, [[META3:![0-9]+]], i64 4, i64 4, [[META6:![0-9]+]], i64 8, i64 8, [[META8:![0-9]+]]}
// CHECK: [[META3]] = !{[[META4:![0-9]+]], [[META4]], i64 0}
// CHECK: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
// CHECK: [[META5]] = !{!"Simple C++ TBAA"}
// CHECK: [[META6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}
// CHECK: [[META7]] = !{!"int", [[META4]], i64 0}
// CHECK: [[META8]] = !{[[META9:![0-9]+]], [[META9]], i64 0}
// CHECK: [[META9]] = !{!"double", [[META4]], i64 0}
61 changes: 0 additions & 61 deletions clang/test/CodeGen/ubsan-bitfield-conversion.c

This file was deleted.

94 changes: 0 additions & 94 deletions clang/test/CodeGenCXX/ubsan-bitfield-conversion.cpp

This file was deleted.

28 changes: 14 additions & 14 deletions clang/test/Driver/fsanitize.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,20 @@
// RUN: %clang --target=%itanium_abi_triple -fsanitize=integer %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-INTEGER -implicit-check-not="-fsanitize-address-use-after-scope"
// CHECK-INTEGER: "-fsanitize={{((signed-integer-overflow|unsigned-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent|implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change|unsigned-shift-base),?){9}"}}

// RUN: %clang -fsanitize=implicit-integer-conversion %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-integer-conversion,CHECK-implicit-integer-conversion-RECOVER
// RUN: %clang -fsanitize=implicit-integer-conversion -fsanitize-recover=implicit-integer-conversion %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-integer-conversion,CHECK-implicit-integer-conversion-RECOVER
// RUN: %clang -fsanitize=implicit-integer-conversion -fno-sanitize-recover=implicit-integer-conversion %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-integer-conversion,CHECK-implicit-integer-conversion-NORECOVER
// RUN: %clang -fsanitize=implicit-integer-conversion -fsanitize-trap=implicit-integer-conversion %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-integer-conversion,CHECK-implicit-integer-conversion-TRAP
// CHECK-implicit-integer-conversion: "-fsanitize={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// CHECK-implicit-integer-conversion-RECOVER: "-fsanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// CHECK-implicit-integer-conversion-RECOVER-NOT: "-fno-sanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// CHECK-implicit-integer-conversion-RECOVER-NOT: "-fsanitize-trap={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// CHECK-implicit-integer-conversion-NORECOVER-NOT: "-fno-sanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}} // ???
// CHECK-implicit-integer-conversion-NORECOVER-NOT: "-fsanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// CHECK-implicit-integer-conversion-NORECOVER-NOT: "-fsanitize-trap={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// CHECK-implicit-integer-conversion-TRAP: "-fsanitize-trap={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// CHECK-implicit-integer-conversion-TRAP-NOT: "-fsanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// CHECK-implicit-integer-conversion-TRAP-NOT: "-fno-sanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// RUN: %clang -fsanitize=implicit-conversion %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-conversion,CHECK-implicit-conversion-RECOVER
// RUN: %clang -fsanitize=implicit-conversion -fsanitize-recover=implicit-conversion %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-conversion,CHECK-implicit-conversion-RECOVER
// RUN: %clang -fsanitize=implicit-conversion -fno-sanitize-recover=implicit-conversion %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-conversion,CHECK-implicit-conversion-NORECOVER
// RUN: %clang -fsanitize=implicit-conversion -fsanitize-trap=implicit-conversion %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-conversion,CHECK-implicit-conversion-TRAP
// CHECK-implicit-conversion: "-fsanitize={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// CHECK-implicit-conversion-RECOVER: "-fsanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// CHECK-implicit-conversion-RECOVER-NOT: "-fno-sanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// CHECK-implicit-conversion-RECOVER-NOT: "-fsanitize-trap={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// CHECK-implicit-conversion-NORECOVER-NOT: "-fno-sanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}} // ???
// CHECK-implicit-conversion-NORECOVER-NOT: "-fsanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// CHECK-implicit-conversion-NORECOVER-NOT: "-fsanitize-trap={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// CHECK-implicit-conversion-TRAP: "-fsanitize-trap={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// CHECK-implicit-conversion-TRAP-NOT: "-fsanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}
// CHECK-implicit-conversion-TRAP-NOT: "-fno-sanitize-recover={{((implicit-unsigned-integer-truncation|implicit-signed-integer-truncation|implicit-integer-sign-change),?){3}"}}

// RUN: %clang -fsanitize=implicit-integer-arithmetic-value-change %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-integer-arithmetic-value-change,CHECK-implicit-integer-arithmetic-value-change-RECOVER
// RUN: %clang -fsanitize=implicit-integer-arithmetic-value-change -fsanitize-recover=implicit-integer-arithmetic-value-change %s -### 2>&1 | FileCheck %s --check-prefixes=CHECK-implicit-integer-arithmetic-value-change,CHECK-implicit-integer-arithmetic-value-change-RECOVER
Expand Down
1 change: 1 addition & 0 deletions clang/test/Driver/mcmodel.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// RUN: FileCheck --check-prefix=AIX-MCMEDIUM-OVERRIDE %s < %t.log
// RUN: not %clang -### -c -mcmodel=lager %s 2>&1 | FileCheck --check-prefix=INVALID %s
// RUN: %clang --target=aarch64 -### -S -mcmodel=large -fno-pic %s 2>&1 | FileCheck --check-prefix=LARGE %s
// RUN: %clang --target=aarch64-apple-macosx -### -S -mcmodel=large %s 2>&1 | FileCheck --check-prefix=LARGE %s
// RUN: not %clang --target=aarch64 -### -S -mcmodel=large -fpic %s 2>&1 | FileCheck --check-prefix=AARCH64-PIC-LARGE %s
// RUN: not %clang -### -c --target=aarch64 -mcmodel=medium %s 2>&1 | FileCheck --check-prefix=ERR-MEDIUM %s
// RUN: not %clang -### -c --target=aarch64 -mcmodel=kernel %s 2>&1 | FileCheck --check-prefix=ERR-KERNEL %s
Expand Down
6 changes: 6 additions & 0 deletions clang/test/InstallAPI/driver-invalid-options.test
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@
// RUN: not clang-installapi -target x86_64-apple-ios-simulator %s -o tmp.tbd 2> %t
// RUN: FileCheck --check-prefix INVALID_INSTALL_NAME -input-file %t %s
// INVALID_INSTALL_NAME: error: no install name specified: add -install_name <path>

/// Check invalid verification mode.
// RUN: not clang-installapi -install_name Foo -target arm64-apple-ios13 \
// RUN: --verify-mode=Invalid -o tmp.tbd 2> %t
// RUN: FileCheck --check-prefix INVALID_VERIFY_MODE -input-file %t %s
// INVALID_VERIFY_MODE: error: invalid value 'Invalid' in '--verify-mode=Invalid'
17 changes: 17 additions & 0 deletions clang/test/Interpreter/inline-asm.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// REQUIRES: host-supports-jit, x86_64-linux
// UNSUPPORTED: system-aix
//
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: split-file %s %t
//
// RUN: cat %t/inline-asm.txt | clang-repl -Xcc="-I%t"

//--- inline-asm.cpp
__asm(".globl _ZSt21ios_base_library_initv");
int x;

//--- inline-asm.txt
#include "inline-asm.cpp"
x = 10;
%quit
7 changes: 5 additions & 2 deletions clang/test/Parser/c2x-typeof-ext-warns.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@
// standards before C23, and Clang has followed suit. Neither compiler exposes
// 'typeof_unqual' as a non-conforming extension.

// Show what happens with the underscored version of the keyword, which is a
// conforming extension.
// Show what happens with the underscored version of the keywords, which are
// conforming extensions.
__typeof__(int) i = 12;
__typeof(int) _i = 12;
__typeof_unqual__(int) u = 12;
__typeof_unqual(int) _u = 12;

// Show what happens with a regular 'typeof' use.
typeof(i) j = 12; // c11-error {{expected function body after function declarator}} \
Expand Down
5 changes: 5 additions & 0 deletions clang/test/SemaCXX/typeof_unqual.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s

typeof_unqual(int) u = 12; // expected-error {{expected function body after function declarator}}
__typeof_unqual(int) _u = 12;
__typeof_unqual__(int) __u = 12;
1 change: 1 addition & 0 deletions clang/tools/clang-repl/ClangRepl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ int main(int argc, const char **argv) {
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmPrinters();
llvm::InitializeAllAsmParsers();

if (OptHostSupportsJit) {
auto J = llvm::orc::LLJITBuilder().create();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,25 @@ class NullPointerAnalysis final
else
JoinedVal.setProperty("is_null", JoinedEnv.makeTopBoolValue());
}

std::optional<WidenResult> widen(QualType Type, Value &Prev,
const Environment &PrevEnv, Value &Current,
Environment &CurrentEnv) override {
switch (compare(Type, Prev, PrevEnv, Current, CurrentEnv)) {
case ComparisonResult::Same:
return WidenResult{&Current, LatticeJoinEffect::Unchanged};
case ComparisonResult::Different: {
auto &CurPtr = cast<PointerValue>(Current);
auto &WidenedPtr =
CurrentEnv.create<PointerValue>(CurPtr.getPointeeLoc());
WidenedPtr.setProperty("is_null", CurrentEnv.makeTopBoolValue());
return WidenResult{&WidenedPtr, LatticeJoinEffect::Changed};
}
case ComparisonResult::Unknown:
return std::nullopt;
}
llvm_unreachable("all cases in switch covered");
}
};

class WideningTest : public Test {
Expand Down Expand Up @@ -846,7 +865,6 @@ TEST_F(WideningTest, JoinDistinctValuesWithDistinctProperties) {
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2", "p3"));
const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
Expand Down Expand Up @@ -889,8 +907,6 @@ TEST_F(WideningTest, JoinDistinctValuesWithSameProperties) {
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
ASSERT_THAT(Results.keys(),
UnorderedElementsAre("p1", "p2", "p3", "p4"));
const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
Expand Down Expand Up @@ -929,19 +945,11 @@ TEST_F(WideningTest, DistinctPointersToTheSameLocationAreEquivalent) {
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");

const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
ASSERT_THAT(FooDecl, NotNull());

const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
ASSERT_THAT(BarDecl, NotNull());

const auto *FooLoc =
cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
const auto &FooLoc =
getLocForDecl<ScalarStorageLocation>(ASTCtx, Env, "Foo");
const auto &BarVal = getValueForDecl<PointerValue>(ASTCtx, Env, "Bar");
EXPECT_EQ(&BarVal.getPointeeLoc(), &FooLoc);
});
}

Expand All @@ -963,18 +971,38 @@ TEST_F(WideningTest, DistinctValuesWithSamePropertiesAreEquivalent) {
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");

const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
ASSERT_THAT(FooDecl, NotNull());

const auto *FooVal = Env.getValue(*FooDecl);
EXPECT_EQ(FooVal->getProperty("is_null"),
const auto &FooVal = getValueForDecl<Value>(ASTCtx, Env, "Foo");
EXPECT_EQ(FooVal.getProperty("is_null"),
&Env.getBoolLiteralValue(false));
});
}

TEST_F(WideningTest, DistinctValuesWithDifferentPropertiesWidenedToTop) {
std::string Code = R"(
void target(bool Cond) {
int *Foo;
int i = 0;
Foo = nullptr;
while (Cond) {
Foo = &i;
}
(void)0;
/*[[p]]*/
}
)";
runDataflow(
Code,
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
ASTContext &ASTCtx) {
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
const auto &FooVal = getValueForDecl<Value>(ASTCtx, Env, "Foo");
ASSERT_THAT(FooVal.getProperty("is_null"), NotNull());
EXPECT_TRUE(areEquivalentValues(*FooVal.getProperty("is_null"),
Env.makeTopBoolValue()));
});
}

class FlowConditionTest : public Test {
protected:
template <typename Matcher>
Expand Down
5 changes: 0 additions & 5 deletions clang/www/c_status.html
Original file line number Diff line number Diff line change
Expand Up @@ -750,11 +750,6 @@ <h2 id="c2x">C23 implementation status</h2>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2379.htm">N2379</a></td>
<td class="unknown" align="center">Unknown</td>
</tr>
<tr>
<td>Floating-point negation and conversion</td>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2416.pdf">N2416</a></td>
<td class="unknown" align="center">Unknown</td>
</tr>
<tr>
<td>Annex F.8 update for implementation extensions and rounding</td>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2384.pdf">N2384</a></td>
Expand Down
7 changes: 5 additions & 2 deletions compiler-rt/lib/hwasan/hwasan_thread_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
// * Start of the shadow memory region is aligned to 2**kShadowBaseAlignment.
// * All stack ring buffers are located within (2**kShadowBaseAlignment)
// sized region below and adjacent to the shadow region.
// * Each ring buffer has a size of (2**N)*4096 where N is in [0, 8), and is
// * Each ring buffer has a size of (2**N)*4096 where N is in [0, 7), and is
// aligned to twice its size. The value of N can be different for each buffer.
//
// These constrains guarantee that, given an address A of any element of the
Expand Down Expand Up @@ -55,7 +55,10 @@ static uptr RingBufferSize() {
uptr desired_bytes = flags()->stack_history_size * sizeof(uptr);
// FIXME: increase the limit to 8 once this bug is fixed:
// https://bugs.llvm.org/show_bug.cgi?id=39030
for (int shift = 1; shift < 7; ++shift) {
// Note that we *cannot* do that on Android, as the runtime will indefinitely
// have to support code that is compiled with ashr, which only works with
// shifts up to 6.
for (int shift = 0; shift < 7; ++shift) {
uptr size = 4096 * (1ULL << shift);
if (size >= desired_bytes)
return size;
Expand Down
27 changes: 10 additions & 17 deletions compiler-rt/lib/ubsan/ubsan_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -555,11 +555,13 @@ static void handleImplicitConversion(ImplicitConversionData *Data,
ReportOptions Opts, ValueHandle Src,
ValueHandle Dst) {
SourceLocation Loc = Data->Loc.acquire();
ErrorType ET = ErrorType::GenericUB;

const TypeDescriptor &SrcTy = Data->FromType;
const TypeDescriptor &DstTy = Data->ToType;

bool SrcSigned = SrcTy.isSignedIntegerTy();
bool DstSigned = DstTy.isSignedIntegerTy();
ErrorType ET = ErrorType::GenericUB;

switch (Data->Kind) {
case ICCK_IntegerTruncation: { // Legacy, no longer used.
Expand Down Expand Up @@ -592,23 +594,14 @@ static void handleImplicitConversion(ImplicitConversionData *Data,

ScopedReport R(Opts, Loc, ET);

// In the case we have a bitfield, we want to explicitly say so in the
// error message.
// FIXME: is it possible to dump the values as hex with fixed width?
if (Data->BitfieldBits)
Diag(Loc, DL_Error, ET,
"implicit conversion from type %0 of value %1 (%2-bit, %3signed) to "
"type %4 changed the value to %5 (%6-bit bitfield, %7signed)")
<< SrcTy << Value(SrcTy, Src) << SrcTy.getIntegerBitWidth()
<< (SrcSigned ? "" : "un") << DstTy << Value(DstTy, Dst)
<< Data->BitfieldBits << (DstSigned ? "" : "un");
else
Diag(Loc, DL_Error, ET,
"implicit conversion from type %0 of value %1 (%2-bit, %3signed) to "
"type %4 changed the value to %5 (%6-bit, %7signed)")
<< SrcTy << Value(SrcTy, Src) << SrcTy.getIntegerBitWidth()
<< (SrcSigned ? "" : "un") << DstTy << Value(DstTy, Dst)
<< DstTy.getIntegerBitWidth() << (DstSigned ? "" : "un");

Diag(Loc, DL_Error, ET,
"implicit conversion from type %0 of value %1 (%2-bit, %3signed) to "
"type %4 changed the value to %5 (%6-bit, %7signed)")
<< SrcTy << Value(SrcTy, Src) << SrcTy.getIntegerBitWidth()
<< (SrcSigned ? "" : "un") << DstTy << Value(DstTy, Dst)
<< DstTy.getIntegerBitWidth() << (DstSigned ? "" : "un");
}

void __ubsan::__ubsan_handle_implicit_conversion(ImplicitConversionData *Data,
Expand Down
1 change: 0 additions & 1 deletion compiler-rt/lib/ubsan/ubsan_handlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ struct ImplicitConversionData {
const TypeDescriptor &FromType;
const TypeDescriptor &ToType;
/* ImplicitConversionCheckKind */ unsigned char Kind;
unsigned int BitfieldBits;
};

/// \brief Implict conversion that changed the value.
Expand Down
1 change: 0 additions & 1 deletion flang/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ build
root
tags
TAGS
*.o
.nfs*
*.sw?
*~
Expand Down
25 changes: 25 additions & 0 deletions flang/include/flang/Common/windows-include.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//===-- include/flang/Common/windows-include.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
//
//===----------------------------------------------------------------------===//
//
// Wrapper around windows.h that works around the name conflicts.
//
//===----------------------------------------------------------------------===//

#ifndef FORTRAN_COMMON_WINDOWS_INCLUDE_H_
#define FORTRAN_COMMON_WINDOWS_INCLUDE_H_

#ifdef _WIN32

#define WIN32_LEAN_AND_MEAN
#define NOMINMAX

#include <windows.h>

#endif // _WIN32

#endif // FORTRAN_COMMON_WINDOWS_INCLUDE_H_
9 changes: 0 additions & 9 deletions flang/lib/Lower/ConvertCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1340,15 +1340,6 @@ static PreparedDummyArgument preparePresentUserCallActualArgument(
} else {
addr = hlfir::genVariableRawAddress(loc, builder, entity);
}
// The last extent created for assumed-rank descriptors must be -1 (18.5.3
// point 5.). This should be done when creating the assumed-size shape for
// consistency.
if (auto baseBoxDummy = mlir::dyn_cast<fir::BaseBoxType>(dummyType))
if (baseBoxDummy.isAssumedRank())
if (const Fortran::semantics::Symbol *sym =
Fortran::evaluate::UnwrapWholeSymbolDataRef(*arg.entity))
if (Fortran::semantics::IsAssumedSizeArray(sym->GetUltimate()))
TODO(loc, "passing assumed-size to assumed-rank array");

// For ranked actual passed to assumed-rank dummy, the cast to assumed-rank
// box is inserted when building the fir.call op. Inserting it here would
Expand Down
31 changes: 27 additions & 4 deletions flang/lib/Lower/OpenMP/ReductionProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "ReductionProcessor.h"

#include "flang/Lower/AbstractConverter.h"
#include "flang/Lower/SymbolMap.h"
#include "flang/Optimizer/Builder/HLFIRTools.h"
#include "flang/Optimizer/Builder/Todo.h"
#include "flang/Optimizer/Dialect/FIRType.h"
Expand Down Expand Up @@ -522,12 +523,20 @@ void ReductionProcessor::addDeclareReduction(
if (reductionSymbols)
reductionSymbols->push_back(symbol);
mlir::Value symVal = converter.getSymbolAddress(*symbol);
auto redType = mlir::cast<fir::ReferenceType>(symVal.getType());
mlir::Type eleType;
auto refType = mlir::dyn_cast_or_null<fir::ReferenceType>(symVal.getType());
if (refType)
eleType = refType.getEleTy();
else
eleType = symVal.getType();

// all arrays must be boxed so that we have convenient access to all the
// information needed to iterate over the array
if (mlir::isa<fir::SequenceType>(redType.getEleTy())) {
hlfir::Entity entity{symVal};
if (mlir::isa<fir::SequenceType>(eleType)) {
// For Host associated symbols, use `SymbolBox` instead
Fortran::lower::SymbolBox symBox =
converter.lookupOneLevelUpSymbol(*symbol);
hlfir::Entity entity{symBox.getAddr()};
entity = genVariableBox(currentLocation, builder, entity);
mlir::Value box = entity.getBase();

Expand All @@ -538,11 +547,25 @@ void ReductionProcessor::addDeclareReduction(
builder.create<fir::StoreOp>(currentLocation, box, alloca);

symVal = alloca;
redType = mlir::cast<fir::ReferenceType>(symVal.getType());
} else if (mlir::isa<fir::BaseBoxType>(symVal.getType())) {
// boxed arrays are passed as values not by reference. Unfortunately,
// we can't pass a box by value to omp.redution_declare, so turn it
// into a reference

auto alloca =
builder.create<fir::AllocaOp>(currentLocation, symVal.getType());
builder.create<fir::StoreOp>(currentLocation, symVal, alloca);
symVal = alloca;
} else if (auto declOp = symVal.getDefiningOp<hlfir::DeclareOp>()) {
symVal = declOp.getBase();
}

// this isn't the same as the by-val and by-ref passing later in the
// pipeline. Both styles assume that the variable is a reference at
// this point
assert(mlir::isa<fir::ReferenceType>(symVal.getType()) &&
"reduction input var is a reference");

reductionVars.push_back(symVal);
}
const bool isByRef = doReductionByRef(reductionVars);
Expand Down
9 changes: 5 additions & 4 deletions flang/lib/Lower/Runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ static void genUnreachable(fir::FirOpBuilder &builder, mlir::Location loc) {
void Fortran::lower::genStopStatement(
Fortran::lower::AbstractConverter &converter,
const Fortran::parser::StopStmt &stmt) {
const bool isError = std::get<Fortran::parser::StopStmt::Kind>(stmt.t) ==
Fortran::parser::StopStmt::Kind::ErrorStop;
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
mlir::Location loc = converter.getCurrentLocation();
Fortran::lower::StatementContext stmtCtx;
Expand Down Expand Up @@ -94,13 +96,12 @@ void Fortran::lower::genStopStatement(
} else {
callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatement)>(loc, builder);
calleeType = callee.getFunctionType();
operands.push_back(
builder.createIntegerConstant(loc, calleeType.getInput(0), 0));
// Default to values are advised in F'2023 11.4 p2.
operands.push_back(builder.createIntegerConstant(
loc, calleeType.getInput(0), isError ? 1 : 0));
}

// Second operand indicates ERROR STOP
bool isError = std::get<Fortran::parser::StopStmt::Kind>(stmt.t) ==
Fortran::parser::StopStmt::Kind::ErrorStop;
operands.push_back(builder.createIntegerConstant(
loc, calleeType.getInput(operands.size()), isError));

Expand Down
5 changes: 4 additions & 1 deletion flang/lib/Optimizer/Builder/IntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5259,9 +5259,12 @@ mlir::Value IntrinsicLibrary::genModulo(mlir::Type resultType,
remainder);
}

auto fastMathFlags = builder.getFastMathFlags();
// F128 arith::RemFOp may be lowered to a runtime call that may be unsupported
// on the target, so generate a call to Fortran Runtime's ModuloReal16.
if (resultType == mlir::FloatType::getF128(builder.getContext()))
if (resultType == mlir::FloatType::getF128(builder.getContext()) ||
(fastMathFlags & mlir::arith::FastMathFlags::ninf) ==
mlir::arith::FastMathFlags::none)
return builder.createConvert(
loc, resultType,
fir::runtime::genModulo(builder, loc, args[0], args[1]));
Expand Down
22 changes: 21 additions & 1 deletion flang/lib/Optimizer/Builder/Runtime/Numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,20 @@ struct ForcedMod16 {
}
};

/// Placeholder for real*10 version of Modulo Intrinsic
struct ForcedModulo10 {
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(ModuloReal10));
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
return [](mlir::MLIRContext *ctx) {
auto fltTy = mlir::FloatType::getF80(ctx);
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
return mlir::FunctionType::get(ctx, {fltTy, fltTy, strTy, intTy},
{fltTy});
};
}
};

/// Placeholder for real*16 version of Modulo Intrinsic
struct ForcedModulo16 {
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(ModuloReal16));
Expand Down Expand Up @@ -349,7 +363,13 @@ mlir::Value fir::runtime::genModulo(fir::FirOpBuilder &builder,

// MODULO is lowered into math operations in intrinsics lowering,
// so genModulo() should only be used for F128 data type now.
if (fltTy.isF128())
if (fltTy.isF32())
func = fir::runtime::getRuntimeFunc<mkRTKey(ModuloReal4)>(loc, builder);
else if (fltTy.isF64())
func = fir::runtime::getRuntimeFunc<mkRTKey(ModuloReal8)>(loc, builder);
else if (fltTy.isF80())
func = fir::runtime::getRuntimeFunc<ForcedModulo10>(loc, builder);
else if (fltTy.isF128())
func = fir::runtime::getRuntimeFunc<ForcedModulo16>(loc, builder);
else
fir::intrinsicTypeTODO(builder, fltTy, loc, "MODULO");
Expand Down
5 changes: 5 additions & 0 deletions flang/lib/Semantics/check-declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,11 @@ void CheckHelper::CheckObjectEntity(
"Component '%s' with ATTRIBUTES(DEVICE) must also be allocatable"_err_en_US,
symbol.name());
}
if (IsAssumedSizeArray(symbol)) {
messages_.Say(
"Object '%s' with ATTRIBUTES(DEVICE) may not be assumed size"_err_en_US,
symbol.name());
}
break;
case common::CUDADataAttr::Managed:
if (!IsAutomatic(symbol) && !IsAllocatable(symbol) &&
Expand Down
4 changes: 1 addition & 3 deletions flang/runtime/command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@
#include <limits>

#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#include "flang/Common/windows-include.h"

// On Windows GetCurrentProcessId returns a DWORD aka uint32_t
#include <processthreadsapi.h>
Expand Down
4 changes: 1 addition & 3 deletions flang/runtime/execute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@
#include <future>
#include <limits>
#ifdef _WIN32
#define LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#include "flang/Common/windows-include.h"
#else
#include <signal.h>
#include <sys/wait.h>
Expand Down
3 changes: 1 addition & 2 deletions flang/runtime/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@
#include <stdlib.h>
#include <sys/stat.h>
#ifdef _WIN32
#define NOMINMAX
#include "flang/Common/windows-include.h"
#include <io.h>
#include <windows.h>
#else
#include <unistd.h>
#endif
Expand Down
4 changes: 1 addition & 3 deletions flang/runtime/lock.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@
#if USE_PTHREADS
#include <pthread.h>
#elif defined(_WIN32)
// Do not define macros for "min" and "max"
#define NOMINMAX
#include <windows.h>
#include "flang/Common/windows-include.h"
#else
#include <mutex>
#endif
Expand Down
29 changes: 24 additions & 5 deletions flang/runtime/numeric-templates.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,12 @@ inline RT_API_ATTRS T RealMod(
if (ISNANTy<T>::compute(a) || ISNANTy<T>::compute(p) ||
ISINFTy<T>::compute(a)) {
return QNANTy<T>::compute();
} else if (ISINFTy<T>::compute(p)) {
return a;
} else if (IS_MODULO && ISINFTy<T>::compute(p)) {
// Other compilers behave consistently for MOD(x, +/-INF)
// and always return x. This is probably related to
// implementation of std::fmod(). Stick to this behavior
// for MOD, but return NaN for MODULO(x, +/-INF).
return QNANTy<T>::compute();
}
T aAbs{ABSTy<T>::compute(a)};
T pAbs{ABSTy<T>::compute(p)};
Expand All @@ -248,8 +252,19 @@ inline RT_API_ATTRS T RealMod(
if (auto pInt{static_cast<std::int64_t>(p)}; p == pInt) {
// Fast exact case for integer operands
auto mod{aInt - (aInt / pInt) * pInt};
if (IS_MODULO && (aInt > 0) != (pInt > 0)) {
mod += pInt;
if constexpr (IS_MODULO) {
if (mod == 0) {
// Return properly signed zero.
return pInt > 0 ? T{0} : -T{0};
}
if ((aInt > 0) != (pInt > 0)) {
mod += pInt;
}
} else {
if (mod == 0) {
// Return properly signed zero.
return aInt > 0 ? T{0} : -T{0};
}
}
return static_cast<T>(mod);
}
Expand Down Expand Up @@ -297,7 +312,11 @@ inline RT_API_ATTRS T RealMod(
}
if constexpr (IS_MODULO) {
if ((a < 0) != (p < 0)) {
tmp += p;
if (tmp == 0.) {
tmp = -tmp;
} else {
tmp += p;
}
}
}
return tmp;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#!/bin/true
Empty file.
Empty file.
3 changes: 3 additions & 0 deletions flang/test/Driver/driver-help-hidden.f90
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@
! CHECK-NEXT: -fversion-loops-for-stride
! CHECK-NEXT: Create unit-strided versions of loops
! CHECK-NEXT: -fxor-operator Enable .XOR. as a synonym of .NEQV.
! CHECK-NEXT: --gcc-install-dir=<value>
! CHECK-NEXT: Use GCC installation in the specified directory. The directory ends with path components like 'lib{,32,64}/gcc{,-cross}/$triple/$version'. Note: executables (e.g. ld) used by the compiler are not overridden by the selected GCC installation
! CHECK-NEXT: --gcc-toolchain=<value> Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. Clang will use the GCC installation with the largest version
! CHECK-NEXT: -gline-directives-only Emit debug line info directives only
! CHECK-NEXT: -gline-tables-only Emit debug line number tables only
! CHECK-NEXT: -gpulibc Link the LLVM C Library for GPUs
Expand Down
3 changes: 3 additions & 0 deletions flang/test/Driver/driver-help.f90
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@
! HELP-NEXT: -fversion-loops-for-stride
! HELP-NEXT: Create unit-strided versions of loops
! HELP-NEXT: -fxor-operator Enable .XOR. as a synonym of .NEQV.
! HELP-NEXT: --gcc-install-dir=<value>
! HELP-NEXT: Use GCC installation in the specified directory. The directory ends with path components like 'lib{,32,64}/gcc{,-cross}/$triple/$version'. Note: executables (e.g. ld) used by the compiler are not overridden by the selected GCC installation
! HELP-NEXT: --gcc-toolchain=<value> Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. Clang will use the GCC installation with the largest version
! HELP-NEXT: -gline-directives-only Emit debug line info directives only
! HELP-NEXT: -gline-tables-only Emit debug line number tables only
! HELP-NEXT: -gpulibc Link the LLVM C Library for GPUs
Expand Down
21 changes: 21 additions & 0 deletions flang/test/Driver/gcc-toolchain-install-dir.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
!! Test that --gcc-toolchain and --gcc-install-dir options are working as expected.
!! It does not test cross-compiling (--sysroot), so crtbegin.o, libgcc/compiler-rt, libc, libFortranRuntime, etc. are not supposed to be affected.
!! PREFIX is captured twice because the driver escapes backslashes (occuring in Windows paths) in the -### output, but not on the "Selected GCC installation:" line.

! RUN: %flang 2>&1 -### -v -o %t %s -no-integrated-as -fuse-ld=ld --target=i386-unknown-linux-gnu --gcc-install-dir=%S/Inputs/basic_cross_linux_tree/usr/lib/gcc/i386-unknown-linux-gnu/10.2.0 | FileCheck %s --check-prefix=CHECK-I386
! RUN: %flang 2>&1 -### -v -o %t %s -no-integrated-as -fuse-ld=ld --target=i386-unknown-linux-gnu --gcc-toolchain=%S/Inputs/basic_cross_linux_tree/usr | FileCheck %s --check-prefix=CHECK-I386
! CHECK-I386: Selected GCC installation: [[PREFIX:[^"]+]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/i386-unknown-linux-gnu/10.2.0
! CHECK-I386: "-fc1" "-triple" "i386-unknown-linux-gnu"
! CHECK-I386: "[[PREFIX:[^"]+]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/i386-unknown-linux-gnu/10.2.0/../../../../i386-unknown-linux-gnu/bin{{/|\\\\}}as"
! CHECK-I386: "[[PREFIX]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/i386-unknown-linux-gnu/10.2.0/../../../../i386-unknown-linux-gnu/bin{{/|\\\\}}ld" {{.*}} "-m" "elf_i386"
! CHECK-I386-SAME: "-L[[PREFIX]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/i386-unknown-linux-gnu/10.2.0"
! CHECK-I386-SAME: "-L[[PREFIX]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/i386-unknown-linux-gnu/10.2.0/../../../../i386-unknown-linux-gnu/lib"

! RUN: %flang 2>&1 -### -v -o %t %s -no-integrated-as -fuse-ld=ld --target=x86_64-unknown-linux-gnu --gcc-install-dir=%S/Inputs/basic_cross_linux_tree/usr/lib/gcc/x86_64-unknown-linux-gnu/10.2.0 | FileCheck %s --check-prefix=CHECK-X86-64
! RUN: %flang 2>&1 -### -v -o %t %s -no-integrated-as -fuse-ld=ld --target=x86_64-unknown-linux-gnu --gcc-toolchain=%S/Inputs/basic_cross_linux_tree/usr | FileCheck %s --check-prefix=CHECK-X86-64
! CHECK-X86-64: Selected GCC installation: [[PREFIX:[^"]+]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/x86_64-unknown-linux-gnu/10.2.0
! CHECK-X86-64: "-fc1" "-triple" "x86_64-unknown-linux-gnu"
! CHECK-X86-64: "[[PREFIX:[^"]+]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/x86_64-unknown-linux-gnu/10.2.0/../../../../x86_64-unknown-linux-gnu/bin{{/|\\\\}}as" "--64"
! CHECK-X86-64: "[[PREFIX]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/x86_64-unknown-linux-gnu/10.2.0/../../../../x86_64-unknown-linux-gnu/bin{{/|\\\\}}ld" {{.*}} "-m" "elf_x86_64"
! CHECK-X86-64-SAME: "-L[[PREFIX]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/x86_64-unknown-linux-gnu/10.2.0"
! CHECK-X86-64-SAME: "-L[[PREFIX]]/Inputs/basic_cross_linux_tree/usr/lib/gcc/x86_64-unknown-linux-gnu/10.2.0/../../../../x86_64-unknown-linux-gnu/lib"
23 changes: 17 additions & 6 deletions flang/test/Lower/HLFIR/assumed-rank-iface.f90
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,20 @@ subroutine int_allocatable_to_assumed_rank_opt(x)
! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_7]] : (!fir.box<!fir.array<?x?xi32>>) -> !fir.box<!fir.array<*:i32>>
! CHECK: fir.call @_QPint_opt_assumed_rank(%[[VAL_11]]) fastmath<contract> : (!fir.box<!fir.array<*:i32>>) -> ()

! TODO: set assumed size last extent to -1.
!subroutine int_r2_assumed_size_to_assumed_rank(x)
! use ifaces, only : int_assumed_rank
! integer :: x(10, *)
! call int_assumed_rank(x)
!end subroutine
subroutine int_r2_assumed_size_to_assumed_rank(x)
use ifaces, only : int_assumed_rank
integer :: x(10, *)
call int_assumed_rank(x)
end subroutine
! CHECK-LABEL: func.func @_QPint_r2_assumed_size_to_assumed_rank(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10x?xi32>> {fir.bindc_name = "x"}) {
! CHECK: %[[VAL_1:.*]] = arith.constant 10 : i64
! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i64) -> index
! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index
! CHECK: %[[VAL_4:.*]] = arith.cmpi sgt, %[[VAL_2]], %[[VAL_3]] : index
! CHECK: %[[VAL_5:.*]] = arith.select %[[VAL_4]], %[[VAL_2]], %[[VAL_3]] : index
! CHECK: %[[VAL_6:.*]] = arith.constant -1 : index
! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_5]], %[[VAL_6]] : (index, index) -> !fir.shape<2>
! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_7]]) {uniq_name = "_QFint_r2_assumed_size_to_assumed_rankEx"} : (!fir.ref<!fir.array<10x?xi32>>, !fir.shape<2>) -> (!fir.box<!fir.array<10x?xi32>>, !fir.ref<!fir.array<10x?xi32>>)
! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]]#0 : (!fir.box<!fir.array<10x?xi32>>) -> !fir.box<!fir.array<*:i32>>
! CHECK: fir.call @_QPint_assumed_rank(%[[VAL_9]]) fastmath<contract> : (!fir.box<!fir.array<*:i32>>) -> ()
18 changes: 10 additions & 8 deletions flang/test/Lower/Intrinsics/modulo.f90
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s -check-prefixes=HONORINF,ALL
! RUN: flang-new -fc1 -menable-no-infs -emit-fir -flang-deprecated-no-hlfir %s -o - | FileCheck %s -check-prefixes=CHECK,ALL

! CHECK-LABEL: func @_QPmodulo_testr(
! CHECK-SAME: %[[arg0:.*]]: !fir.ref<f64>{{.*}}, %[[arg1:.*]]: !fir.ref<f64>{{.*}}, %[[arg2:.*]]: !fir.ref<f64>{{.*}}) {
! ALL-LABEL: func @_QPmodulo_testr(
! ALL-SAME: %[[arg0:.*]]: !fir.ref<f64>{{.*}}, %[[arg1:.*]]: !fir.ref<f64>{{.*}}, %[[arg2:.*]]: !fir.ref<f64>{{.*}}) {
subroutine modulo_testr(r, a, p)
real(8) :: r, a, p
! CHECK-DAG: %[[a:.*]] = fir.load %[[arg1]] : !fir.ref<f64>
! CHECK-DAG: %[[p:.*]] = fir.load %[[arg2]] : !fir.ref<f64>
! ALL-DAG: %[[a:.*]] = fir.load %[[arg1]] : !fir.ref<f64>
! ALL-DAG: %[[p:.*]] = fir.load %[[arg2]] : !fir.ref<f64>
! HONORINF: %[[res:.*]] = fir.call @_FortranAModuloReal8(%[[a]], %[[p]]
! CHECK-DAG: %[[rem:.*]] = arith.remf %[[a]], %[[p]] {{.*}}: f64
! CHECK-DAG: %[[zero:.*]] = arith.constant 0.000000e+00 : f64
! CHECK-DAG: %[[remNotZero:.*]] = arith.cmpf une, %[[rem]], %[[zero]] {{.*}} : f64
Expand All @@ -15,12 +17,12 @@ subroutine modulo_testr(r, a, p)
! CHECK-DAG: %[[mustAddP:.*]] = arith.andi %[[remNotZero]], %[[signDifferent]] : i1
! CHECK-DAG: %[[remPlusP:.*]] = arith.addf %[[rem]], %[[p]] {{.*}}: f64
! CHECK: %[[res:.*]] = arith.select %[[mustAddP]], %[[remPlusP]], %[[rem]] : f64
! CHECK: fir.store %[[res]] to %[[arg0]] : !fir.ref<f64>
! ALL: fir.store %[[res]] to %[[arg0]] : !fir.ref<f64>
r = modulo(a, p)
end subroutine

! CHECK-LABEL: func @_QPmodulo_testi(
! CHECK-SAME: %[[arg0:.*]]: !fir.ref<i64>{{.*}}, %[[arg1:.*]]: !fir.ref<i64>{{.*}}, %[[arg2:.*]]: !fir.ref<i64>{{.*}}) {
! ALL-LABEL: func @_QPmodulo_testi(
! ALL-SAME: %[[arg0:.*]]: !fir.ref<i64>{{.*}}, %[[arg1:.*]]: !fir.ref<i64>{{.*}}, %[[arg2:.*]]: !fir.ref<i64>{{.*}}) {
subroutine modulo_testi(r, a, p)
integer(8) :: r, a, p
! CHECK-DAG: %[[a:.*]] = fir.load %[[arg1]] : !fir.ref<i64>
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenMP/parallel-reduction-array.f90
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ program reduce
! CHECK: %[[VAL_1:.*]] = arith.constant 3 : index
! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1>
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_2]]) {uniq_name = "_QFEi"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<3xi32>>, !fir.ref<!fir.array<3xi32>>)
! CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_3]]#1(%[[VAL_2]]) : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xi32>>
! CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_3]]#0(%[[VAL_2]]) : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xi32>>
! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.box<!fir.array<3xi32>>
! CHECK: fir.store %[[VAL_4]] to %[[VAL_5]] : !fir.ref<!fir.box<!fir.array<3xi32>>>
! CHECK: omp.parallel byref reduction(@add_reduction_byref_box_3xi32 %[[VAL_5]] -> %[[VAL_6:.*]] : !fir.ref<!fir.box<!fir.array<3xi32>>>) {
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenMP/parallel-reduction-array2.f90
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ program reduce
! CHECK: %[[VAL_1:.*]] = arith.constant 3 : index
! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1>
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_2]]) {uniq_name = "_QFEi"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<3xi32>>, !fir.ref<!fir.array<3xi32>>)
! CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_3]]#1(%[[VAL_2]]) : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xi32>>
! CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_3]]#0(%[[VAL_2]]) : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xi32>>
! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.box<!fir.array<3xi32>>
! CHECK: fir.store %[[VAL_4]] to %[[VAL_5]] : !fir.ref<!fir.box<!fir.array<3xi32>>>
! CHECK: omp.parallel byref reduction(@add_reduction_byref_box_3xi32 %[[VAL_5]] -> %[[VAL_6:.*]] : !fir.ref<!fir.box<!fir.array<3xi32>>>) {
Expand Down
125 changes: 125 additions & 0 deletions flang/test/Lower/OpenMP/parallel-reduction3.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py

! The script is designed to make adding checks to
! a test case fast, it is *not* designed to be authoritative
! about what constitutes a good test! The CHECK should be
! minimized and named to reflect the test intent.

! RUN: bbc -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s
! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s



! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_Uxi32 : !fir.ref<!fir.box<!fir.array<?xi32>>> init {
! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.array<?xi32>>>):
! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32
! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index
! CHECK: %[[VAL_4:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_3]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index)
! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]]#1 : (index) -> !fir.shape<1>
! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.array<?xi32>, %[[VAL_4]]#1 {bindc_name = ".tmp"}
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]](%[[VAL_5]]) {uniq_name = ".tmp"} : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.array<?xi32>>)
! CHECK: hlfir.assign %[[VAL_1]] to %[[VAL_7]]#0 : i32, !fir.box<!fir.array<?xi32>>
! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box<!fir.array<?xi32>>
! CHECK: fir.store %[[VAL_7]]#0 to %[[VAL_8]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
! CHECK: omp.yield(%[[VAL_8]] : !fir.ref<!fir.box<!fir.array<?xi32>>>)

! CHECK-LABEL: } combiner {
! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.array<?xi32>>>, %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.array<?xi32>>>):
! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index
! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_4]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index)
! CHECK: %[[VAL_6:.*]] = fir.shape_shift %[[VAL_5]]#0, %[[VAL_5]]#1 : (index, index) -> !fir.shapeshift<1>
! CHECK: %[[VAL_7:.*]] = arith.constant 1 : index
! CHECK: fir.do_loop %[[VAL_8:.*]] = %[[VAL_7]] to %[[VAL_5]]#1 step %[[VAL_7]] unordered {
! CHECK: %[[VAL_9:.*]] = fir.array_coor %[[VAL_2]](%[[VAL_6]]) %[[VAL_8]] : (!fir.box<!fir.array<?xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32>
! CHECK: %[[VAL_10:.*]] = fir.array_coor %[[VAL_3]](%[[VAL_6]]) %[[VAL_8]] : (!fir.box<!fir.array<?xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32>
! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_9]] : !fir.ref<i32>
! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_10]] : !fir.ref<i32>
! CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_11]], %[[VAL_12]] : i32
! CHECK: fir.store %[[VAL_13]] to %[[VAL_9]] : !fir.ref<i32>
! CHECK: }
! CHECK: omp.yield(%[[VAL_0]] : !fir.ref<!fir.box<!fir.array<?xi32>>>)
! CHECK: }

! CHECK-LABEL: func.func @_QPs(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "x"}) {
! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsEi"}
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_1]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i32) -> i64
! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i64) -> index
! CHECK: %[[VAL_7:.*]] = arith.constant 0 : index
! CHECK: %[[VAL_8:.*]] = arith.cmpi sgt, %[[VAL_6]], %[[VAL_7]] : index
! CHECK: %[[VAL_9:.*]] = arith.select %[[VAL_8]], %[[VAL_6]], %[[VAL_7]] : index
! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.array<?xi32>, %[[VAL_9]] {bindc_name = "c", uniq_name = "_QFsEc"}
! CHECK: %[[VAL_11:.*]] = fir.shape %[[VAL_9]] : (index) -> !fir.shape<1>
! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]](%[[VAL_11]]) {uniq_name = "_QFsEc"} : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.array<?xi32>>)
! CHECK: %[[VAL_13:.*]] = arith.constant 0 : i32
! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_12]]#0 : i32, !fir.box<!fir.array<?xi32>>
! CHECK: omp.parallel {
! CHECK: %[[VAL_14:.*]] = fir.alloca i32 {adapt.valuebyref, pinned}
! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_14]] {uniq_name = "_QFsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_16:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_17:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_18:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_19:.*]] = fir.alloca !fir.box<!fir.array<?xi32>>
! CHECK: fir.store %[[VAL_12]]#0 to %[[VAL_19]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_Uxi32 %[[VAL_19]] -> %[[VAL_20:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>) for (%[[VAL_21:.*]]) : i32 = (%[[VAL_16]]) to (%[[VAL_17]]) inclusive step (%[[VAL_18]]) {
! CHECK: fir.store %[[VAL_21]] to %[[VAL_15]]#1 : !fir.ref<i32>
! CHECK: %[[VAL_22:.*]]:2 = hlfir.declare %[[VAL_20]] {uniq_name = "_QFsEc"} : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> (!fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.ref<!fir.box<!fir.array<?xi32>>>)
! CHECK: %[[VAL_23:.*]] = fir.load %[[VAL_22]]#0 : !fir.ref<!fir.box<!fir.array<?xi32>>>
! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<i32>
! CHECK: %[[VAL_25:.*]] = arith.constant 0 : index
! CHECK: %[[VAL_26:.*]]:3 = fir.box_dims %[[VAL_23]], %[[VAL_25]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index)
! CHECK: %[[VAL_27:.*]] = fir.shape %[[VAL_26]]#1 : (index) -> !fir.shape<1>
! CHECK: %[[VAL_28:.*]] = hlfir.elemental %[[VAL_27]] unordered : (!fir.shape<1>) -> !hlfir.expr<?xi32> {
! CHECK: ^bb0(%[[VAL_29:.*]]: index):
! CHECK: %[[VAL_30:.*]] = arith.constant 0 : index
! CHECK: %[[VAL_31:.*]]:3 = fir.box_dims %[[VAL_23]], %[[VAL_30]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index)
! CHECK: %[[VAL_32:.*]] = arith.constant 1 : index
! CHECK: %[[VAL_33:.*]] = arith.subi %[[VAL_31]]#0, %[[VAL_32]] : index
! CHECK: %[[VAL_34:.*]] = arith.addi %[[VAL_29]], %[[VAL_33]] : index
! CHECK: %[[VAL_35:.*]] = hlfir.designate %[[VAL_23]] (%[[VAL_34]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
! CHECK: %[[VAL_36:.*]] = fir.load %[[VAL_35]] : !fir.ref<i32>
! CHECK: %[[VAL_37:.*]] = arith.addi %[[VAL_36]], %[[VAL_24]] : i32
! CHECK: hlfir.yield_element %[[VAL_37]] : i32
! CHECK: }
! CHECK: %[[VAL_38:.*]] = fir.load %[[VAL_22]]#0 : !fir.ref<!fir.box<!fir.array<?xi32>>>
! CHECK: hlfir.assign %[[VAL_28]] to %[[VAL_38]] : !hlfir.expr<?xi32>, !fir.box<!fir.array<?xi32>>
! CHECK: hlfir.destroy %[[VAL_28]] : !hlfir.expr<?xi32>
! CHECK: omp.yield
! CHECK: }
! CHECK: omp.terminator
! CHECK: }
! CHECK: %[[VAL_39:.*]] = arith.constant 1 : index
! CHECK: %[[VAL_40:.*]] = hlfir.designate %[[VAL_12]]#0 (%[[VAL_39]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
! CHECK: %[[VAL_41:.*]] = fir.load %[[VAL_40]] : !fir.ref<i32>
! CHECK: %[[VAL_42:.*]] = arith.constant 5050 : i32
! CHECK: %[[VAL_43:.*]] = arith.cmpi ne, %[[VAL_41]], %[[VAL_42]] : i32
! CHECK: cf.cond_br %[[VAL_43]], ^bb1, ^bb2
! CHECK: ^bb1:
! CHECK: %[[VAL_44:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_45:.*]] = arith.constant false
! CHECK: %[[VAL_46:.*]] = arith.constant false
! CHECK: %[[VAL_47:.*]] = fir.call @_FortranAStopStatement(%[[VAL_44]], %[[VAL_45]], %[[VAL_46]]) fastmath<contract> : (i32, i1, i1) -> none
! CHECK: fir.unreachable
! CHECK: ^bb2:
! CHECK: return
! CHECK: }
! CHECK: func.func private @_FortranAStopStatement(i32, i1, i1) -> none attributes {fir.runtime}

subroutine s(x)
integer :: x
integer :: c(x)
c = 0
!$omp parallel do reduction(+:c)
do i = 1, 100
c = c + i
end do
!$omp end parallel do

if (c(1) /= 5050) stop 1
end subroutine s
Loading