Index: lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -41,6 +41,7 @@ #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/Constant.h" +#include "llvm/IR/ConstantRange.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfoMetadata.h" @@ -3510,7 +3511,7 @@ } return ComputeNumSignBits(Src, Depth + 1); } - case ISD::CONCAT_VECTORS: + case ISD::CONCAT_VECTORS: { // Determine the minimum number of sign bits across all demanded // elts of the input vectors. Early out if the result is already 1. Tmp = std::numeric_limits::max(); @@ -3528,6 +3529,17 @@ assert(Tmp <= VTBits && "Failed to determine minimum sign bits"); return Tmp; } + case ISD::LOAD: { + LoadSDNode *LD = cast(Op); + if (const MDNode *Ranges = LD->getRanges()) { + ConstantRange CR = getConstantRangeFromMetadata(*Ranges); + return std::min(CR.getLower().getNumSignBits(), + CR.getUpper().getNumSignBits()); + } + + break; + } + } // If we are looking at the loaded value of the SDNode. if (Op.getResNo() == 0) { Index: test/CodeGen/AMDGPU/load-range-metadata-sign-bits.ll =================================================================== --- /dev/null +++ test/CodeGen/AMDGPU/load-range-metadata-sign-bits.ll @@ -0,0 +1,45 @@ +; RUN: llc -mtriple=amdgcn-amd-amdhsa -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefix=GCN %s + +; GCN-LABEL: {{^}}range_metata_sext_i8_signed_range: +; GCN: flat_load_dword [[LOAD:v[0-9]+]] +; GCN-NOT: [[LOAD]] +define i32 @range_metata_sext_i8_signed_range(i32 addrspace(1)* %ptr) { + %val = load i32, i32 addrspace(1)* %ptr, !range !0 + %shl = shl i32 %val, 23 + %ashr = ashr i32 %shl, 23 + ret i32 %ashr +} + +; GCN-LABEL: {{^}}range_metata_sext_i8_signed_range_too_low: +; GCN: flat_load_dword [[LOAD:v[0-9]+]] +; GCN: v_bfe_i32 v{{[0-9]+}}, [[LOAD]], 0, 9 +define i32 @range_metata_sext_i8_signed_range_too_low(i32 addrspace(1)* %ptr) { + %val = load i32, i32 addrspace(1)* %ptr, !range !1 + %shl = shl i32 %val, 23 + %ashr = ashr i32 %shl, 23 + ret i32 %ashr +} + +; GCN-LABEL: {{^}}range_metata_sext_i8_signed_range_1: +; GCN: flat_load_dword [[LOAD:v[0-9]+]] +; GCN: v_bfe_i32 v{{[0-9]+}}, [[LOAD]], 0, 8 +define i32 @range_metata_sext_i8_signed_range_1(i32 addrspace(1)* %ptr) { + %val = load i32, i32 addrspace(1)* %ptr, !range !0 + %shl = shl i32 %val, 24 + %ashr = ashr i32 %shl, 24 + ret i32 %ashr +} + +; GCN-LABEL: {{^}}range_metata_sext_i8_neg_neg_range: +; GCN: flat_load_dword [[LOAD:v[0-9]+]] +; GCN-NOT [[LOAD]] +define i32 @range_metata_sext_i8_neg_neg_range(i32 addrspace(1)* %ptr) { + %val = load i32, i32 addrspace(1)* %ptr, !range !2 + %shl = shl i32 %val, 23 + %ashr = ashr i32 %shl, 23 + ret i32 %ashr +} + +!0 = !{i32 -127, i32 128} +!1 = !{i32 -127, i32 256} +!2 = !{i32 -127, i32 -64}