[clang] [FMV][RISCV] Add __riscv_feature_bits.length check (PR #110098)

Piyou Chen via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 26 02:45:58 PDT 2024


https://github.com/BeMg updated https://github.com/llvm/llvm-project/pull/110098

>From 838c6669d2f4464b9b528b0d633ad363b92e3b57 Mon Sep 17 00:00:00 2001
From: Piyou Chen <piyou.chen at sifive.com>
Date: Thu, 26 Sep 2024 02:16:56 -0700
Subject: [PATCH 1/2] [FMV][RISCV] Check FeatureBits.length before test all
 version

---
 clang/lib/CodeGen/CGBuiltin.cpp               |  33 +++-
 clang/lib/CodeGen/CodeGenFunction.cpp         |  32 ++-
 clang/lib/CodeGen/CodeGenFunction.h           |   1 +
 clang/test/CodeGen/attr-target-clones-riscv.c | 184 +++++++++++-------
 .../CodeGenCXX/attr-target-clones-riscv.cpp   | 184 +++++++++++-------
 5 files changed, 274 insertions(+), 160 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 249aead33ad73d..6af6f166575142 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -14534,8 +14534,9 @@ Value *CodeGenFunction::EmitRISCVCpuSupports(const CallExpr *E) {
   return EmitRISCVCpuSupports(ArrayRef<StringRef>(FeatureStr));
 }
 
-static Value *loadRISCVFeatureBits(unsigned Index, CGBuilderTy &Builder,
-                                   CodeGenModule &CGM) {
+static Value *loadRISCVFeatureBitsCommon(ArrayRef<llvm::Value *> GEPIndices,
+                                         CGBuilderTy &Builder,
+                                         CodeGenModule &CGM) {
   llvm::Type *Int32Ty = Builder.getInt32Ty();
   llvm::Type *Int64Ty = Builder.getInt64Ty();
   llvm::ArrayType *ArrayOfInt64Ty =
@@ -14544,14 +14545,32 @@ static Value *loadRISCVFeatureBits(unsigned Index, CGBuilderTy &Builder,
   llvm::Constant *RISCVFeaturesBits =
       CGM.CreateRuntimeVariable(StructTy, "__riscv_feature_bits");
   cast<llvm::GlobalValue>(RISCVFeaturesBits)->setDSOLocal(true);
-  Value *IndexVal = llvm::ConstantInt::get(Int32Ty, Index);
-  llvm::Value *GEPIndices[] = {Builder.getInt32(0), Builder.getInt32(1),
-                               IndexVal};
   Value *Ptr =
       Builder.CreateInBoundsGEP(StructTy, RISCVFeaturesBits, GEPIndices);
-  Value *FeaturesBit =
+  Value *FeaturesVal =
       Builder.CreateAlignedLoad(Int64Ty, Ptr, CharUnits::fromQuantity(8));
-  return FeaturesBit;
+  return FeaturesVal;
+}
+
+static Value *loadRISCVFeatureBitsLength(CGBuilderTy &Builder,
+                                         CodeGenModule &CGM) {
+  llvm::Value *GEPIndices[] = {Builder.getInt32(0), Builder.getInt32(0)};
+  return loadRISCVFeatureBitsCommon(GEPIndices, Builder, CGM);
+}
+
+static Value *loadRISCVFeatureBits(unsigned Index, CGBuilderTy &Builder,
+                                   CodeGenModule &CGM) {
+  llvm::Type *Int32Ty = Builder.getInt32Ty();
+  Value *IndexVal = llvm::ConstantInt::get(Int32Ty, Index);
+  llvm::Value *GEPIndices[] = {Builder.getInt32(0), Builder.getInt32(1),
+                               IndexVal};
+  return loadRISCVFeatureBitsCommon(GEPIndices, Builder, CGM);
+}
+
+llvm::Value *CodeGenFunction::EmitRISCVFeatureBitsLengthCond() {
+  return Builder.CreateICmpULE(
+      loadRISCVFeatureBitsLength(Builder, CGM),
+      Builder.getInt64(llvm::RISCVISAInfo::FeatureBitSize));
 }
 
 Value *CodeGenFunction::EmitRISCVCpuSupports(ArrayRef<StringRef> FeaturesStrs) {
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index eda96f3e352ce3..9e558195aa6daa 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2945,6 +2945,10 @@ void CodeGenFunction::EmitRISCVMultiVersionResolver(
                getPriorityFromAttrString(RHS.Conditions.Features[0]);
       });
 
+  llvm::BasicBlock *LengthBlock = CurBlock;
+  llvm::BasicBlock *VersionBlock = createBasicBlock("version_begin", Resolver);
+  CurBlock = VersionBlock;
+
   // Check the each candidate function.
   for (unsigned Index = 0; Index < CurrOptions.size(); Index++) {
 
@@ -2970,22 +2974,28 @@ void CodeGenFunction::EmitRISCVMultiVersionResolver(
     // (__riscv_feature_bits.features[i] & REQUIRED_BITMASK) ==
     // REQUIRED_BITMASK
     //
+    // First, check __riscv_feature_bits.length <=
+    // llvm::RISCVISAInfo::FeatureBitSize. This ensures that the
+    // __riscv_feature_bits object at runtime has the same length as on the
+    // compiler side.
+    //
+    // Second, 
     // When condition is met, return this version of the function.
     // Otherwise, try the next version.
     //
-    // if (FeaturesConditionVersion1)
+    //
+    // if (__riscv_feature_bits.features.length <=
+    // llvm::RISCVISAInfo::FeatureBitSize) {
+    //   if (FeaturesConditionVersion1)
     //     return Version1;
-    // else if (FeaturesConditionVersion2)
+    //   else if (FeaturesConditionVersion2)
     //     return Version2;
-    // else if (FeaturesConditionVersion3)
+    //   else if (FeaturesConditionVersion3)
     //     return Version3;
-    // ...
-    // else
-    //     return DefaultVersion;
+    //   ...
+    // }
+    // return DefaultVersion;
 
-    // TODO: Add a condition to check the length before accessing elements.
-    // Without checking the length first, we may access an incorrect memory
-    // address when using different versions.
     llvm::SmallVector<StringRef, 8> CurrTargetAttrFeats;
 
     for (auto &Feat : TargetAttrFeats) {
@@ -3009,6 +3019,10 @@ void CodeGenFunction::EmitRISCVMultiVersionResolver(
     CurBlock = ElseBlock;
   }
 
+  Builder.SetInsertPoint(LengthBlock);
+  llvm::Value *FeatsLengthCond = EmitRISCVFeatureBitsLengthCond();
+  Builder.CreateCondBr(FeatsLengthCond, VersionBlock, CurBlock);
+
   // Finally, emit the default one.
   if (HasDefault) {
     Builder.SetInsertPoint(CurBlock);
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 3e2abbd9bc1094..5e1cb1a6e421cb 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4715,6 +4715,7 @@ class CodeGenFunction : public CodeGenTypeCache {
 
   llvm::Value *EmitRISCVCpuSupports(const CallExpr *E);
   llvm::Value *EmitRISCVCpuSupports(ArrayRef<StringRef> FeaturesStrs);
+  llvm::Value *EmitRISCVFeatureBitsLengthCond();
   llvm::Value *EmitRISCVCpuInit();
 
   void AddAMDGPUFenceAddressSpaceMMRA(llvm::Instruction *Inst,
diff --git a/clang/test/CodeGen/attr-target-clones-riscv.c b/clang/test/CodeGen/attr-target-clones-riscv.c
index 4a5dea91e22769..47900effb673ea 100644
--- a/clang/test/CodeGen/attr-target-clones-riscv.c
+++ b/clang/test/CodeGen/attr-target-clones-riscv.c
@@ -59,10 +59,14 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7()
 // CHECK-LABEL: define weak_odr ptr @foo1.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 4096
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 4096
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 4096
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 4096
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @foo1._m
 // CHECK:       resolver_else:
@@ -90,17 +94,21 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7()
 // CHECK-LABEL: define weak_odr ptr @foo2.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 268435456
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 268435456
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE2:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 268435456
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 268435456
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @foo2._zbb
 // CHECK:       resolver_else:
-// CHECK-NEXT:    [[TMP3:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP4:%.*]] = and i64 [[TMP3]], 4096
-// CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64 [[TMP4]], 4096
-// CHECK-NEXT:    br i1 [[TMP5]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
+// CHECK-NEXT:    [[TMP5:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP6:%.*]] = and i64 [[TMP5]], 4096
+// CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i64 [[TMP6]], 4096
+// CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2]]
 // CHECK:       resolver_return1:
 // CHECK-NEXT:    ret ptr @foo2._m
 // CHECK:       resolver_else2:
@@ -122,10 +130,14 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7()
 // CHECK-LABEL: define weak_odr ptr @foo3.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 268435460
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 268435460
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 268435460
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 268435460
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @foo3._c_zbb
 // CHECK:       resolver_else:
@@ -147,10 +159,14 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7()
 // CHECK-LABEL: define weak_odr ptr @foo4.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 270532608
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 270532608
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 270532608
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 270532608
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @foo4._v_zbb
 // CHECK:       resolver_else:
@@ -166,6 +182,10 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7()
 // CHECK-LABEL: define weak_odr ptr @foo5.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[TRY_VERSION]]
+// CHECK:       try_version:
 // CHECK-NEXT:    ret ptr @foo5.default
 //
 //
@@ -184,10 +204,14 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7()
 // CHECK-LABEL: define weak_odr ptr @foo6.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 576460752303423488
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 576460752303423488
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 576460752303423488
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 576460752303423488
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @foo6._zvkt
 // CHECK:       resolver_else:
@@ -221,24 +245,28 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7()
 // CHECK-LABEL: define weak_odr ptr @foo7.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 268435456
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 268435456
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 268435456
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 268435456
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @foo7._zbb
 // CHECK:       resolver_else:
-// CHECK-NEXT:    [[TMP3:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP4:%.*]] = and i64 [[TMP3]], 134217728
-// CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64 [[TMP4]], 134217728
-// CHECK-NEXT:    br i1 [[TMP5]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
+// CHECK-NEXT:    [[TMP5:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP6:%.*]] = and i64 [[TMP5]], 134217728
+// CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i64 [[TMP6]], 134217728
+// CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
 // CHECK:       resolver_return1:
 // CHECK-NEXT:    ret ptr @foo7._zba
 // CHECK:       resolver_else2:
-// CHECK-NEXT:    [[TMP6:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP7:%.*]] = and i64 [[TMP6]], 402653184
-// CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 402653184
-// CHECK-NEXT:    br i1 [[TMP8]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK-NEXT:    [[TMP8:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP8]], 402653184
+// CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 402653184
+// CHECK-NEXT:    br i1 [[TMP10]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4]]
 // CHECK:       resolver_return3:
 // CHECK-NEXT:    ret ptr @foo7._zba_zbb
 // CHECK:       resolver_else4:
@@ -272,24 +300,28 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7()
 // CHECK-LABEL: define weak_odr ptr @foo8.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 402653184
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 402653184
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 402653184
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 402653184
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @foo8._zba_zbb
 // CHECK:       resolver_else:
-// CHECK-NEXT:    [[TMP3:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP4:%.*]] = and i64 [[TMP3]], 268435456
-// CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64 [[TMP4]], 268435456
-// CHECK-NEXT:    br i1 [[TMP5]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
+// CHECK-NEXT:    [[TMP5:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP6:%.*]] = and i64 [[TMP5]], 268435456
+// CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i64 [[TMP6]], 268435456
+// CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
 // CHECK:       resolver_return1:
 // CHECK-NEXT:    ret ptr @foo8._zbb
 // CHECK:       resolver_else2:
-// CHECK-NEXT:    [[TMP6:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP7:%.*]] = and i64 [[TMP6]], 134217728
-// CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 134217728
-// CHECK-NEXT:    br i1 [[TMP8]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK-NEXT:    [[TMP8:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP8]], 134217728
+// CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 134217728
+// CHECK-NEXT:    br i1 [[TMP10]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4]]
 // CHECK:       resolver_return3:
 // CHECK-NEXT:    ret ptr @foo8._zba
 // CHECK:       resolver_else4:
@@ -323,24 +355,28 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7()
 // CHECK-LABEL: define weak_odr ptr @foo9.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 402653184
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 402653184
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 402653184
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 402653184
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @foo9._zba_zbb
 // CHECK:       resolver_else:
-// CHECK-NEXT:    [[TMP3:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP4:%.*]] = and i64 [[TMP3]], 134217728
-// CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64 [[TMP4]], 134217728
-// CHECK-NEXT:    br i1 [[TMP5]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
+// CHECK-NEXT:    [[TMP5:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP6:%.*]] = and i64 [[TMP5]], 134217728
+// CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i64 [[TMP6]], 134217728
+// CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
 // CHECK:       resolver_return1:
 // CHECK-NEXT:    ret ptr @foo9._zba
 // CHECK:       resolver_else2:
-// CHECK-NEXT:    [[TMP6:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP7:%.*]] = and i64 [[TMP6]], 268435456
-// CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 268435456
-// CHECK-NEXT:    br i1 [[TMP8]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK-NEXT:    [[TMP8:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP8]], 268435456
+// CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 268435456
+// CHECK-NEXT:    br i1 [[TMP10]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4]]
 // CHECK:       resolver_return3:
 // CHECK-NEXT:    ret ptr @foo9._zbb
 // CHECK:       resolver_else4:
@@ -374,24 +410,28 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7()
 // CHECK-LABEL: define weak_odr ptr @foo10.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 402653184
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 402653184
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 402653184
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 402653184
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @foo10._zba_zbb
 // CHECK:       resolver_else:
-// CHECK-NEXT:    [[TMP3:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP4:%.*]] = and i64 [[TMP3]], 268435456
-// CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64 [[TMP4]], 268435456
-// CHECK-NEXT:    br i1 [[TMP5]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
+// CHECK-NEXT:    [[TMP5:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP6:%.*]] = and i64 [[TMP5]], 268435456
+// CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i64 [[TMP6]], 268435456
+// CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
 // CHECK:       resolver_return1:
 // CHECK-NEXT:    ret ptr @foo10._zbb
 // CHECK:       resolver_else2:
-// CHECK-NEXT:    [[TMP6:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP7:%.*]] = and i64 [[TMP6]], 134217728
-// CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 134217728
-// CHECK-NEXT:    br i1 [[TMP8]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK-NEXT:    [[TMP8:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP8]], 134217728
+// CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 134217728
+// CHECK-NEXT:    br i1 [[TMP10]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4]]
 // CHECK:       resolver_return3:
 // CHECK-NEXT:    ret ptr @foo10._zba
 // CHECK:       resolver_else4:
diff --git a/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp b/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp
index d53e5c0520e6c7..fe64662141891a 100644
--- a/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp
+++ b/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp
@@ -58,10 +58,14 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5()+ foo6() + foo7() +
 // CHECK-LABEL: define weak_odr ptr @_Z4foo1v.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 4096
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 4096
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 4096
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 4096
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @_Z4foo1v._m
 // CHECK:       resolver_else:
@@ -89,17 +93,21 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5()+ foo6() + foo7() +
 // CHECK-LABEL: define weak_odr ptr @_Z4foo2v.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 268435456
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 268435456
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE2:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 268435456
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 268435456
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @_Z4foo2v._zbb
 // CHECK:       resolver_else:
-// CHECK-NEXT:    [[TMP3:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP4:%.*]] = and i64 [[TMP3]], 4096
-// CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64 [[TMP4]], 4096
-// CHECK-NEXT:    br i1 [[TMP5]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
+// CHECK-NEXT:    [[TMP5:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP6:%.*]] = and i64 [[TMP5]], 4096
+// CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i64 [[TMP6]], 4096
+// CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2]]
 // CHECK:       resolver_return1:
 // CHECK-NEXT:    ret ptr @_Z4foo2v._m
 // CHECK:       resolver_else2:
@@ -121,10 +129,14 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5()+ foo6() + foo7() +
 // CHECK-LABEL: define weak_odr ptr @_Z4foo3v.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 268435460
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 268435460
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 268435460
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 268435460
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @_Z4foo3v._c_zbb
 // CHECK:       resolver_else:
@@ -146,10 +158,14 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5()+ foo6() + foo7() +
 // CHECK-LABEL: define weak_odr ptr @_Z4foo4v.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 270532608
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 270532608
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 270532608
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 270532608
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @_Z4foo4v._v_zbb
 // CHECK:       resolver_else:
@@ -165,6 +181,10 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5()+ foo6() + foo7() +
 // CHECK-LABEL: define weak_odr ptr @_Z4foo5v.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[TRY_VERSION]]
+// CHECK:       try_version:
 // CHECK-NEXT:    ret ptr @_Z4foo5v.default
 //
 //
@@ -183,10 +203,14 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5()+ foo6() + foo7() +
 // CHECK-LABEL: define weak_odr ptr @_Z4foo6v.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 576460752303423488
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 576460752303423488
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 576460752303423488
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 576460752303423488
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @_Z4foo6v._zvkt
 // CHECK:       resolver_else:
@@ -220,24 +244,28 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5()+ foo6() + foo7() +
 // CHECK-LABEL: define weak_odr ptr @_Z4foo7v.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 268435456
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 268435456
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 268435456
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 268435456
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @_Z4foo7v._zbb
 // CHECK:       resolver_else:
-// CHECK-NEXT:    [[TMP3:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP4:%.*]] = and i64 [[TMP3]], 134217728
-// CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64 [[TMP4]], 134217728
-// CHECK-NEXT:    br i1 [[TMP5]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
+// CHECK-NEXT:    [[TMP5:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP6:%.*]] = and i64 [[TMP5]], 134217728
+// CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i64 [[TMP6]], 134217728
+// CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
 // CHECK:       resolver_return1:
 // CHECK-NEXT:    ret ptr @_Z4foo7v._zba
 // CHECK:       resolver_else2:
-// CHECK-NEXT:    [[TMP6:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP7:%.*]] = and i64 [[TMP6]], 402653184
-// CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 402653184
-// CHECK-NEXT:    br i1 [[TMP8]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK-NEXT:    [[TMP8:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP8]], 402653184
+// CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 402653184
+// CHECK-NEXT:    br i1 [[TMP10]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4]]
 // CHECK:       resolver_return3:
 // CHECK-NEXT:    ret ptr @_Z4foo7v._zba_zbb
 // CHECK:       resolver_else4:
@@ -271,24 +299,28 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5()+ foo6() + foo7() +
 // CHECK-LABEL: define weak_odr ptr @_Z4foo8v.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 402653184
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 402653184
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 402653184
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 402653184
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @_Z4foo8v._zba_zbb
 // CHECK:       resolver_else:
-// CHECK-NEXT:    [[TMP3:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP4:%.*]] = and i64 [[TMP3]], 268435456
-// CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64 [[TMP4]], 268435456
-// CHECK-NEXT:    br i1 [[TMP5]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
+// CHECK-NEXT:    [[TMP5:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP6:%.*]] = and i64 [[TMP5]], 268435456
+// CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i64 [[TMP6]], 268435456
+// CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
 // CHECK:       resolver_return1:
 // CHECK-NEXT:    ret ptr @_Z4foo8v._zbb
 // CHECK:       resolver_else2:
-// CHECK-NEXT:    [[TMP6:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP7:%.*]] = and i64 [[TMP6]], 134217728
-// CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 134217728
-// CHECK-NEXT:    br i1 [[TMP8]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK-NEXT:    [[TMP8:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP8]], 134217728
+// CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 134217728
+// CHECK-NEXT:    br i1 [[TMP10]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4]]
 // CHECK:       resolver_return3:
 // CHECK-NEXT:    ret ptr @_Z4foo8v._zba
 // CHECK:       resolver_else4:
@@ -322,24 +354,28 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5()+ foo6() + foo7() +
 // CHECK-LABEL: define weak_odr ptr @_Z4foo9v.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 402653184
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 402653184
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 402653184
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 402653184
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @_Z4foo9v._zba_zbb
 // CHECK:       resolver_else:
-// CHECK-NEXT:    [[TMP3:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP4:%.*]] = and i64 [[TMP3]], 134217728
-// CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64 [[TMP4]], 134217728
-// CHECK-NEXT:    br i1 [[TMP5]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
+// CHECK-NEXT:    [[TMP5:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP6:%.*]] = and i64 [[TMP5]], 134217728
+// CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i64 [[TMP6]], 134217728
+// CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
 // CHECK:       resolver_return1:
 // CHECK-NEXT:    ret ptr @_Z4foo9v._zba
 // CHECK:       resolver_else2:
-// CHECK-NEXT:    [[TMP6:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP7:%.*]] = and i64 [[TMP6]], 268435456
-// CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 268435456
-// CHECK-NEXT:    br i1 [[TMP8]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK-NEXT:    [[TMP8:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP8]], 268435456
+// CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 268435456
+// CHECK-NEXT:    br i1 [[TMP10]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4]]
 // CHECK:       resolver_return3:
 // CHECK-NEXT:    ret ptr @_Z4foo9v._zbb
 // CHECK:       resolver_else4:
@@ -373,24 +409,28 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5()+ foo6() + foo7() +
 // CHECK-LABEL: define weak_odr ptr @_Z5foo10v.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_riscv_feature_bits(ptr null)
-// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 402653184
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 402653184
-// CHECK-NEXT:    br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__riscv_feature_bits, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i64 [[TMP0]], 2
+// CHECK-NEXT:    br i1 [[TMP1]], label [[TRY_VERSION:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK:       try_version:
+// CHECK-NEXT:    [[TMP2:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP2]], 402653184
+// CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 402653184
+// CHECK-NEXT:    br i1 [[TMP4]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @_Z5foo10v._zba_zbb
 // CHECK:       resolver_else:
-// CHECK-NEXT:    [[TMP3:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP4:%.*]] = and i64 [[TMP3]], 268435456
-// CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64 [[TMP4]], 268435456
-// CHECK-NEXT:    br i1 [[TMP5]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
+// CHECK-NEXT:    [[TMP5:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP6:%.*]] = and i64 [[TMP5]], 268435456
+// CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i64 [[TMP6]], 268435456
+// CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
 // CHECK:       resolver_return1:
 // CHECK-NEXT:    ret ptr @_Z5foo10v._zbb
 // CHECK:       resolver_else2:
-// CHECK-NEXT:    [[TMP6:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
-// CHECK-NEXT:    [[TMP7:%.*]] = and i64 [[TMP6]], 134217728
-// CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 134217728
-// CHECK-NEXT:    br i1 [[TMP8]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]]
+// CHECK-NEXT:    [[TMP8:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
+// CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP8]], 134217728
+// CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 134217728
+// CHECK-NEXT:    br i1 [[TMP10]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4]]
 // CHECK:       resolver_return3:
 // CHECK-NEXT:    ret ptr @_Z5foo10v._zba
 // CHECK:       resolver_else4:

>From 7fa8abdf1d1de4a25db4893b0406fe0285b14d72 Mon Sep 17 00:00:00 2001
From: Piyou Chen <piyou.chen at sifive.com>
Date: Thu, 26 Sep 2024 02:45:42 -0700
Subject: [PATCH 2/2] Fixup clang-format

---
 clang/lib/CodeGen/CodeGenFunction.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 9e558195aa6daa..6589d1eeb8c6d9 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2979,7 +2979,7 @@ void CodeGenFunction::EmitRISCVMultiVersionResolver(
     // __riscv_feature_bits object at runtime has the same length as on the
     // compiler side.
     //
-    // Second, 
+    // Second,
     // When condition is met, return this version of the function.
     // Otherwise, try the next version.
     //



More information about the cfe-commits mailing list