Index: llvm/lib/Target/AMDGPU/AMDGPURemoveIncompatibleFunctions.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPURemoveIncompatibleFunctions.cpp +++ llvm/lib/Target/AMDGPU/AMDGPURemoveIncompatibleFunctions.cpp @@ -52,11 +52,16 @@ /// Checks a single function, returns true if the function must be deleted. bool checkFunction(Function &F); + /// Check and remove any incompatible attributes + /// that will not be supported by specific targets. + void removeInvalidAttributes(Function &F); + bool runOnModule(Module &M) override { assert(TM->getTargetTriple().isAMDGCN()); SmallVector FnsToDelete; for (Function &F : M) { + removeInvalidAttributes(F); if (checkFunction(F)) FnsToDelete.push_back(&F); } @@ -109,6 +114,37 @@ } } // end anonymous namespace +void AMDGPURemoveIncompatibleFunctions::removeInvalidAttributes(Function &F) { + if (F.isDeclaration()) + return; + + const GCNSubtarget *ST = + static_cast(TM->getSubtargetImpl(F)); + bool isGfx10AndAbove = ST->getGeneration() >= AMDGPUSubtarget::GFX10; + Attribute FSAttr = F.getFnAttribute("target-features"); + + // Remove wavefrontsize32 attribute for targets below gfx10 + if (!isGfx10AndAbove && FSAttr.isValid() && + FSAttr.getValueAsString().contains("+wavefrontsize32")) { + std::string UpdatedFeatures; + SmallVector Features; + FSAttr.getValueAsString().split(Features, ','); + for (StringRef Feature : Features) { + if (Feature != "+wavefrontsize32") { + UpdatedFeatures.append(Feature); + UpdatedFeatures.append(","); + } + } + F.removeFnAttr("target-features"); + if (!UpdatedFeatures.empty()) { + // Remove last comma. + UpdatedFeatures.pop_back(); + F.addFnAttr("target-features", UpdatedFeatures); + } + } + return; +} + bool AMDGPURemoveIncompatibleFunctions::checkFunction(Function &F) { if (F.isDeclaration()) return false; Index: llvm/test/CodeGen/AMDGPU/remove-incompatible-attributes.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AMDGPU/remove-incompatible-attributes.ll @@ -0,0 +1,34 @@ +; RUN: llc -march=amdgcn -mcpu=gfx90a -mattr=+wavefrontsize64 -stop-after=amdgpu-remove-incompatible-functions < %s | FileCheck -check-prefix=GFX90A %s + +; Check if wavefrontsize32 attribute is removed after the pass +define void @test1(ptr %out) #0 { + %1 = tail call i32 @llvm.read_register.i32(metadata !0) + %2 = tail call i32 @llvm.ctpop.i32(i32 %1) + store i32 %2, ptr %out, align 4 + ret void +} + +; Check that pass doesn't cause issue with other target-features +define amdgpu_kernel void @test2() #1 { + ret void +} + +; Check if wavefrontsize32 attribute is removed but not the other target-features after the pass +define amdgpu_kernel void @test3() #2 { + ret void +} + +declare i32 @llvm.read_register.i32(metadata) +declare i32 @llvm.ctpop.i32(i32) + +!0 = !{!"exec_lo"} + +; GFX90A: @test1(ptr %out) #0 +; GFX90A: @test2() #1 +; GFX90A: @test3() #1 +; GFX90A: attributes #0 = { "target-cpu"="gfx90a" "target-features"="+wavefrontsize64" } +; GFX90A: attributes #1 = { "target-cpu"="gfx90a" "target-features"="+xnack,+wavefrontsize64" } + +attributes #0 = { "target-features"="+wavefrontsize32" } +attributes #1 = { "target-features"="+xnack" } +attributes #2 = { "target-features"="+wavefrontsize32,+xnack" }